From 940052bcbcd50081244f995e3cad89eaa2cc1c04 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 18 Mar 2024 17:09:49 +0100 Subject: hwmon: (aspeed-g6-pwm-tacho): Make use of pwmchip_parent() accessor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit struct pwm_chip::dev is about to change. To not have to touch this driver in the same commit as struct pwm_chip::dev, use the accessor function provided for exactly this purpose. Acked-by: Guenter Roeck Link: https://lore.kernel.org/r/5c6a11dd10cd29e0f7bfaa1fdef145523347cb58.1710777536.git.u.kleine-koenig@pengutronix.de Signed-off-by: Uwe Kleine-König --- drivers/hwmon/aspeed-g6-pwm-tach.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/aspeed-g6-pwm-tach.c b/drivers/hwmon/aspeed-g6-pwm-tach.c index 597b3b019d49..64def5e4cdf6 100644 --- a/drivers/hwmon/aspeed-g6-pwm-tach.c +++ b/drivers/hwmon/aspeed-g6-pwm-tach.c @@ -195,7 +195,7 @@ static int aspeed_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, expect_period = div64_u64(ULLONG_MAX, (u64)priv->clk_rate); expect_period = min(expect_period, state->period); - dev_dbg(chip->dev, "expect period: %lldns, duty_cycle: %lldns", + dev_dbg(pwmchip_parent(chip), "expect period: %lldns, duty_cycle: %lldns", expect_period, state->duty_cycle); /* * Pick the smallest value for div_h so that div_l can be the biggest @@ -218,12 +218,12 @@ static int aspeed_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, if (div_l > 255) div_l = 255; - dev_dbg(chip->dev, "clk source: %ld div_h %lld, div_l : %lld\n", + dev_dbg(pwmchip_parent(chip), "clk source: %ld div_h %lld, div_l : %lld\n", priv->clk_rate, div_h, div_l); /* duty_pt = duty_cycle * (PERIOD + 1) / period */ duty_pt = div64_u64(state->duty_cycle * priv->clk_rate, (u64)NSEC_PER_SEC * (div_l + 1) << div_h); - dev_dbg(chip->dev, "duty_cycle = %lld, duty_pt = %d\n", + dev_dbg(pwmchip_parent(chip), "duty_cycle = %lld, duty_pt = %d\n", state->duty_cycle, duty_pt); /* -- cgit v1.2.3 From 79dedfadb79e527ca4dc6f3727dace96e3333f82 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 18 Mar 2024 17:09:50 +0100 Subject: hwmon: (aspeed-g6-pwm-tacho): Make use of devm_pwmchip_alloc() function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This prepares the aspeed-g6-pwm-tacho driver to further changes of the pwm core outlined in the commit introducing devm_pwmchip_alloc(). There is no intended semantical change and the driver should behave as before. Acked-by: Guenter Roeck Link: https://lore.kernel.org/r/e95e41eea5a138ae206c9116ba3cb1d9e0178284.1710777536.git.u.kleine-koenig@pengutronix.de Signed-off-by: Uwe Kleine-König --- drivers/hwmon/aspeed-g6-pwm-tach.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/aspeed-g6-pwm-tach.c b/drivers/hwmon/aspeed-g6-pwm-tach.c index 64def5e4cdf6..332c02216668 100644 --- a/drivers/hwmon/aspeed-g6-pwm-tach.c +++ b/drivers/hwmon/aspeed-g6-pwm-tach.c @@ -136,7 +136,6 @@ struct aspeed_pwm_tach_data { struct clk *clk; struct reset_control *reset; unsigned long clk_rate; - struct pwm_chip chip; bool tach_present[TACH_ASPEED_NR_TACHS]; u32 tach_divisor; }; @@ -144,7 +143,7 @@ struct aspeed_pwm_tach_data { static inline struct aspeed_pwm_tach_data * aspeed_pwm_chip_to_data(struct pwm_chip *chip) { - return container_of(chip, struct aspeed_pwm_tach_data, chip); + return pwmchip_get_drvdata(chip); } static int aspeed_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, @@ -459,6 +458,7 @@ static int aspeed_pwm_tach_probe(struct platform_device *pdev) int ret; struct device_node *child; struct aspeed_pwm_tach_data *priv; + struct pwm_chip *chip; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -487,11 +487,14 @@ static int aspeed_pwm_tach_probe(struct platform_device *pdev) if (ret) return ret; - priv->chip.dev = dev; - priv->chip.ops = &aspeed_pwm_ops; - priv->chip.npwm = PWM_ASPEED_NR_PWMS; + chip = devm_pwmchip_alloc(dev, PWM_ASPEED_NR_PWMS, 0); + if (IS_ERR(chip)) + return PTR_ERR(chip); - ret = devm_pwmchip_add(dev, &priv->chip); + pwmchip_set_drvdata(chip, priv); + chip->ops = &aspeed_pwm_ops; + + ret = devm_pwmchip_add(dev, chip); if (ret) return dev_err_probe(dev, ret, "Failed to add PWM chip\n"); -- cgit v1.2.3 From df43ade4cb49f5b4a18bf9e737117dfbb7dbd21a Mon Sep 17 00:00:00 2001 From: Tobias Jakobi Date: Sun, 10 Mar 2024 23:07:09 +0100 Subject: hwmon: (dell-smm) Add Dell G5 5505 to DMI table Enables reading the speed of the CPU and GPU fan on the G5. Signed-off-by: Tobias Jakobi Reviewed-by: Armin Wolf Link: https://lore.kernel.org/r/20240310220710.896230-1-tjakobi@math.uni-bielefeld.de Signed-off-by: Guenter Roeck --- drivers/hwmon/dell-smm-hwmon.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c index efcf78673e74..cefa2a054525 100644 --- a/drivers/hwmon/dell-smm-hwmon.c +++ b/drivers/hwmon/dell-smm-hwmon.c @@ -1214,6 +1214,13 @@ static const struct dmi_system_id i8k_dmi_table[] __initconst = { DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "G5 5590"), }, }, + { + .ident = "Dell G5 5505", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "G5 5505"), + }, + }, { .ident = "Dell Inspiron", .matches = { -- cgit v1.2.3 From c7506a2b5a8233c32bd05353aac7c7b3af05d85f Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Mon, 18 Mar 2024 23:14:05 +0530 Subject: hwmon: (pmbus/mp2975) Fix IRQ masking The MP2971/MP2973 use a custom 16bit register format for SMBALERT_MASK which doesn't follow the PMBUS specification. Map the PMBUS defined bits used by the common code onto the custom format used by MPS and since the SMBALERT_MASK is currently never read by common code only implement the mapping for write transactions. Signed-off-by: Patrick Rudolph Signed-off-by: Naresh Solanki Link: https://lore.kernel.org/r/20240318174406.3782306-1-naresh.solanki@9elements.com Signed-off-by: Guenter Roeck --- drivers/hwmon/pmbus/mp2975.c | 77 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/pmbus/mp2975.c b/drivers/hwmon/pmbus/mp2975.c index e5fa10b3b8bc..953c02a2aeb5 100644 --- a/drivers/hwmon/pmbus/mp2975.c +++ b/drivers/hwmon/pmbus/mp2975.c @@ -392,6 +392,82 @@ static int mp2973_read_word_data(struct i2c_client *client, int page, return ret; } +static int mp2973_write_word_data(struct i2c_client *client, int page, + int reg, u16 word) +{ + u8 target, mask; + int ret; + + if (reg != PMBUS_SMBALERT_MASK) + return -ENODATA; + + /* + * Vendor-specific SMBALERT_MASK register with 16 maskable bits. + */ + ret = pmbus_read_word_data(client, 0, 0, PMBUS_SMBALERT_MASK); + if (ret < 0) + return ret; + + target = word & 0xff; + mask = word >> 8; + +/* + * Set/Clear 'bit' in 'ret' based on condition followed by define for each bit in SMBALERT_MASK. + * Also bit 2 & 15 are reserved. + */ +#define SWAP(val, mask, cond, bit) (((mask) & (cond)) ? ((val) & ~BIT(bit)) : ((val) | BIT(bit))) + +#define MP2973_TEMP_OT 0 +#define MP2973_VIN_UVLO 1 +#define MP2973_VIN_OVP 3 +#define MP2973_MTP_FAULT 4 +#define MP2973_OTHER_COMM 5 +#define MP2973_MTP_BLK_TRIG 6 +#define MP2973_PACKET_ERROR 7 +#define MP2973_INVALID_DATA 8 +#define MP2973_INVALID_COMMAND 9 +#define MP2973_IOUT_OC_LV 10 +#define MP2973_IOUT_OC 11 +#define MP2973_VOUT_MAX_MIN_WARNING 12 +#define MP2973_VOLTAGE_UV 13 +#define MP2973_VOLTAGE_OV 14 + + switch (target) { + case PMBUS_STATUS_CML: + ret = SWAP(ret, mask, PB_CML_FAULT_INVALID_DATA, MP2973_INVALID_DATA); + ret = SWAP(ret, mask, PB_CML_FAULT_INVALID_COMMAND, MP2973_INVALID_COMMAND); + ret = SWAP(ret, mask, PB_CML_FAULT_OTHER_COMM, MP2973_OTHER_COMM); + ret = SWAP(ret, mask, PB_CML_FAULT_PACKET_ERROR, MP2973_PACKET_ERROR); + break; + case PMBUS_STATUS_VOUT: + ret = SWAP(ret, mask, PB_VOLTAGE_UV_FAULT, MP2973_VOLTAGE_UV); + ret = SWAP(ret, mask, PB_VOLTAGE_OV_FAULT, MP2973_VOLTAGE_OV); + break; + case PMBUS_STATUS_IOUT: + ret = SWAP(ret, mask, PB_IOUT_OC_FAULT, MP2973_IOUT_OC); + ret = SWAP(ret, mask, PB_IOUT_OC_LV_FAULT, MP2973_IOUT_OC_LV); + break; + case PMBUS_STATUS_TEMPERATURE: + ret = SWAP(ret, mask, PB_TEMP_OT_FAULT, MP2973_TEMP_OT); + break; + /* + * Map remaining bits to MFR specific to let the PMBUS core mask + * those bits by default. + */ + case PMBUS_STATUS_MFR_SPECIFIC: + ret = SWAP(ret, mask, BIT(1), MP2973_VIN_UVLO); + ret = SWAP(ret, mask, BIT(3), MP2973_VIN_OVP); + ret = SWAP(ret, mask, BIT(4), MP2973_MTP_FAULT); + ret = SWAP(ret, mask, BIT(6), MP2973_MTP_BLK_TRIG); + break; + default: + return 0; + } +#undef SWAP + + return pmbus_write_word_data(client, 0, PMBUS_SMBALERT_MASK, ret); +} + static int mp2975_read_word_data(struct i2c_client *client, int page, int phase, int reg) { @@ -907,6 +983,7 @@ static struct pmbus_driver_info mp2973_info = { PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_POUT | PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT, .read_word_data = mp2973_read_word_data, + .write_word_data = mp2973_write_word_data, #if IS_ENABLED(CONFIG_SENSORS_MP2975_REGULATOR) .num_regulators = 1, .reg_desc = mp2975_reg_desc, -- cgit v1.2.3 From b18c01a4c82cf853add1255b51f7a4f1b3a39dc0 Mon Sep 17 00:00:00 2001 From: Kousik Sanagavarapu Date: Mon, 18 Mar 2024 21:08:35 +0530 Subject: hwmon: (lm70) fix links in doc and comments Update links in the documentation and in-code comments which point to the datasheet. The current links don't work because National Semiconductor (which is the original manufacturer of this chip) has been a part of Texas Instruments since 2011 and http://www.national.com/ doesn't work anymore. Fixes: e1a8e913f97e ("[PATCH] lm70: New hardware monitoring driver") Signed-off-by: Kousik Sanagavarapu Link: https://lore.kernel.org/r/20240318154540.90613-3-five231003@gmail.com Signed-off-by: Guenter Roeck --- Documentation/hwmon/lm70.rst | 2 +- drivers/hwmon/lm70.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/hwmon') diff --git a/Documentation/hwmon/lm70.rst b/Documentation/hwmon/lm70.rst index 11303a7e16a8..02ed60dddffb 100644 --- a/Documentation/hwmon/lm70.rst +++ b/Documentation/hwmon/lm70.rst @@ -5,7 +5,7 @@ Supported chips: * National Semiconductor LM70 - Datasheet: http://www.national.com/pf/LM/LM70.html + Datasheet: https://www.ti.com/product/LM70 * Texas Instruments TMP121/TMP123 diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c index c20a749fc7f2..481e4e1f8f4f 100644 --- a/drivers/hwmon/lm70.c +++ b/drivers/hwmon/lm70.c @@ -6,9 +6,9 @@ * Copyright (C) 2006 Kaiwan N Billimoria * * The LM70 communicates with a host processor via an SPI/Microwire Bus - * interface. The complete datasheet is available at National's website + * interface. The complete datasheet is available at TI's website * here: - * http://www.national.com/pf/LM/LM70.html + * https://www.ti.com/product/LM70 */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -- cgit v1.2.3 From 71113b9be4259d4bd396f22034653a9035ba07fb Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Wed, 20 Mar 2024 16:43:17 +0800 Subject: hwmon: (acpi_power_meter) Ensure IPMI space handler is ready on Dell systems The following error can be observed at boot: [ 3.717920] ACPI Error: No handler for Region [SYSI] (00000000ab9e62c5) [IPMI] (20230628/evregion-130) [ 3.717928] ACPI Error: Region IPMI (ID=7) has no handler (20230628/exfldio-261) [ 3.717936] No Local Variables are initialized for Method [_GHL] [ 3.717938] No Arguments are initialized for method [_GHL] [ 3.717940] ACPI Error: Aborting method \_SB.PMI0._GHL due to previous error (AE_NOT_EXIST) (20230628/psparse-529) [ 3.717949] ACPI Error: Aborting method \_SB.PMI0._PMC due to previous error (AE_NOT_EXIST) (20230628/psparse-529) [ 3.717957] ACPI: \_SB_.PMI0: _PMC evaluation failed: AE_NOT_EXIST On Dell systems several methods of acpi_power_meter access variables in IPMI region [0], so wait until IPMI space handler is installed by acpi_ipmi and also wait until SMI is selected to make the space handler fully functional. Since the dependency is inside BIOS's ASL code and it's not discoverable, so use this fixup is a hack to workaround BIOS issue. [0] https://www.dell.com/support/manuals/en-us/redhat-enterprise-linux-v8.0/rhel8_rn_pub/advanced-configuration-and-power-interface-acpi-error-messages-displayed-in-dmesg?guid=guid-0d5ae482-1977-42cf-b417-3ed5c3f5ee62 Signed-off-by: Kai-Heng Feng Link: https://lore.kernel.org/r/20240320084317.366853-2-kai.heng.feng@canonical.com [groeck: Simplified added code] Signed-off-by: Guenter Roeck --- drivers/hwmon/acpi_power_meter.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c index 703666b95bf4..6c8a9c863528 100644 --- a/drivers/hwmon/acpi_power_meter.c +++ b/drivers/hwmon/acpi_power_meter.c @@ -883,6 +883,22 @@ static int acpi_power_meter_add(struct acpi_device *device) strcpy(acpi_device_class(device), ACPI_POWER_METER_CLASS); device->driver_data = resource; +#if IS_REACHABLE(CONFIG_ACPI_IPMI) + /* + * On Dell systems several methods of acpi_power_meter access + * variables in IPMI region, so wait until IPMI space handler is + * installed by acpi_ipmi and also wait until SMI is selected to make + * the space handler fully functional. + */ + if (dmi_match(DMI_SYS_VENDOR, "Dell Inc.")) { + struct acpi_device *ipi_device = acpi_dev_get_first_match_dev("IPI0001", NULL, -1); + + if (ipi_device && acpi_wait_for_acpi_ipmi()) + dev_warn(&device->dev, "Waiting for ACPI IPMI timeout"); + acpi_dev_put(ipi_device); + } +#endif + res = read_capabilities(resource); if (res) goto exit_free; -- cgit v1.2.3 From 04f175954daee54e7c50dd831ee15e8a36fe5648 Mon Sep 17 00:00:00 2001 From: Radu Sabau Date: Thu, 21 Mar 2024 16:21:43 +0200 Subject: hwmon: (pmbus) Add driver for ADP1050 Add support for ADP1050 Digital Controller for Isolated Power Supplies with PMBus interface Voltage, Current and Temperature Monitor. The ADP1050 implements several features to enable a robust system of parallel and redundant operation for customers who require high availability. The device can measure voltage, current and temperature that can be used in different techniques to identify and safely shut down an erroneous power supply in parallel operation mode. Signed-off-by: Radu Sabau Link: https://lore.kernel.org/r/20240321142201.10330-2-radu.sabau@analog.com [groeck: Fixed corrupted link in documentation] Signed-off-by: Guenter Roeck --- Documentation/hwmon/adp1050.rst | 64 +++++++++++++++++++++++++++++++++++++++++ Documentation/hwmon/index.rst | 1 + drivers/hwmon/pmbus/Kconfig | 10 +++++++ drivers/hwmon/pmbus/Makefile | 1 + drivers/hwmon/pmbus/adp1050.c | 58 +++++++++++++++++++++++++++++++++++++ 5 files changed, 134 insertions(+) create mode 100644 Documentation/hwmon/adp1050.rst create mode 100644 drivers/hwmon/pmbus/adp1050.c (limited to 'drivers/hwmon') diff --git a/Documentation/hwmon/adp1050.rst b/Documentation/hwmon/adp1050.rst new file mode 100644 index 000000000000..8fa937064886 --- /dev/null +++ b/Documentation/hwmon/adp1050.rst @@ -0,0 +1,64 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Kernel driver adp1050 +===================== + +Supported chips: + + * Analog Devices ADP1050 + + Prefix: 'adp1050' + + Addresses scanned: I2C 0x70 - 0x77 + + Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ADP1050.pdf + +Authors: + + - Radu Sabau + + +Description +----------- + +This driver supprts hardware monitoring for Analog Devices ADP1050 Digital +Controller for Isolated Power Supply with PMBus interface. + +The ADP1050 is an advanced digital controller with a PMBus™ +interface targeting high density, high efficiency dc-to-dc power +conversion used to monitor system temperatures, voltages and currents. +Through the PMBus interface, the device can monitor input/output voltages, +input current and temperature. + +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. + +Platform data support +--------------------- + +The driver supports standard PMBus driver platform data. + +Sysfs Attributes +---------------- + +================= ======================================== +in1_label "vin" +in1_input Measured input voltage +in1_alarm Input voltage alarm +in2_label "vout1" +in2_input Measured output voltage +in2_crit Critical maximum output voltage +in2_crit_alarm Output voltage high alarm +in2_lcrit Critical minimum output voltage +in2_lcrit_alarm Output voltage critical low alarm +curr1_label "iin" +curr1_input Measured input current. +curr1_alarm Input current alarm +temp1_input Measured temperature +temp1_crit Critical high temperature +temp1_crit_alarm Chip temperature critical high alarm +================= ======================================== diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst index 1ca7a4fe1f8f..9a4fd576e6f6 100644 --- a/Documentation/hwmon/index.rst +++ b/Documentation/hwmon/index.rst @@ -33,6 +33,7 @@ Hardware Monitoring Kernel Drivers adm1266 adm1275 adm9240 + adp1050 ads7828 adt7410 adt7411 diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig index 557ae0c414b0..38e794d83cc3 100644 --- a/drivers/hwmon/pmbus/Kconfig +++ b/drivers/hwmon/pmbus/Kconfig @@ -57,6 +57,16 @@ config SENSORS_ADM1275 This driver can also be built as a module. If so, the module will be called adm1275. +config SENSORS_ADP1050 + tristate "Analog Devices ADP1050 digital controller for Power Supplies" + help + If you say yes here you get hardware monitoring support for Analog + Devices ADP1050 digital controller for isolated power supply with + PMBus interface. + + This driver can also be built as a module. If so, the module will + be called adp1050. + config SENSORS_BEL_PFE tristate "Bel PFE Compatible Power Supplies" help diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile index f14ecf03ad77..95a8dea5e5ed 100644 --- a/drivers/hwmon/pmbus/Makefile +++ b/drivers/hwmon/pmbus/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_SENSORS_PMBUS) += pmbus.o obj-$(CONFIG_SENSORS_ACBEL_FSG032) += acbel-fsg032.o obj-$(CONFIG_SENSORS_ADM1266) += adm1266.o obj-$(CONFIG_SENSORS_ADM1275) += adm1275.o +obj-$(CONFIG_SENSORS_ADP1050) += adp1050.o obj-$(CONFIG_SENSORS_BEL_PFE) += bel-pfe.o obj-$(CONFIG_SENSORS_BPA_RS600) += bpa-rs600.o obj-$(CONFIG_SENSORS_DELTA_AHE50DC_FAN) += delta-ahe50dc-fan.o diff --git a/drivers/hwmon/pmbus/adp1050.c b/drivers/hwmon/pmbus/adp1050.c new file mode 100644 index 000000000000..0a49bea8e13b --- /dev/null +++ b/drivers/hwmon/pmbus/adp1050.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Hardware monitoring driver for Analog Devices ADP1050 + * + * Copyright (C) 2024 Analog Devices, Inc. + */ +#include +#include +#include +#include +#include +#include +#include +#include "pmbus.h" + +static struct pmbus_driver_info adp1050_info = { + .pages = 1, + .format[PSC_VOLTAGE_IN] = linear, + .format[PSC_VOLTAGE_OUT] = linear, + .format[PSC_CURRENT_IN] = linear, + .format[PSC_TEMPERATURE] = linear, + .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT + | PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT + | PMBUS_HAVE_IIN | PMBUS_HAVE_TEMP + | PMBUS_HAVE_STATUS_TEMP, +}; + +static int adp1050_probe(struct i2c_client *client) +{ + return pmbus_do_probe(client, &adp1050_info); +} + +static const struct i2c_device_id adp1050_id[] = { + {"adp1050", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, adp1050_id); + +static const struct of_device_id adp1050_of_match[] = { + { .compatible = "adi,adp1050"}, + {} +}; +MODULE_DEVICE_TABLE(of, adp1050_of_match); + +static struct i2c_driver adp1050_driver = { + .driver = { + .name = "adp1050", + .of_match_table = adp1050_of_match, + }, + .probe = adp1050_probe, + .id_table = adp1050_id, +}; +module_i2c_driver(adp1050_driver); + +MODULE_AUTHOR("Radu Sabau "); +MODULE_DESCRIPTION("Analog Devices ADP1050 HWMON PMBus Driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(PMBUS); -- cgit v1.2.3 From c84e93da8bc1c460cb53478d3c9d51cbbd718308 Mon Sep 17 00:00:00 2001 From: Seiji Nishikawa Date: Mon, 25 Mar 2024 13:59:13 +0900 Subject: hwmon: (dell-smm) Add Dell Precision 7540 to fan control whitelist Add Precision 7540 to the fan control whitelist, in addition to 7510. Signed-off-by: Seiji Nishikawa Link: https://lore.kernel.org/r/20240325045913.385853-2-snishika@redhat.com Signed-off-by: Guenter Roeck --- drivers/hwmon/dell-smm-hwmon.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c index cefa2a054525..48a81c64f00d 100644 --- a/drivers/hwmon/dell-smm-hwmon.c +++ b/drivers/hwmon/dell-smm-hwmon.c @@ -1513,6 +1513,14 @@ static const struct dmi_system_id i8k_whitelist_fan_control[] __initconst = { }, .driver_data = (void *)&i8k_fan_control_data[I8K_FAN_34A3_35A3], }, + { + .ident = "Dell Precision 7540", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Precision 7540"), + }, + .driver_data = (void *)&i8k_fan_control_data[I8K_FAN_34A3_35A3], + }, { .ident = "Dell XPS 13 7390", .matches = { -- cgit v1.2.3 From 9c3793629d7aa40cc07ac9dafc6df0bb21593585 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 25 Mar 2024 14:41:56 +0200 Subject: hwmon: (pmbus/adp1050) Don't use "proxy" headers Update header inclusions to follow IWYU (Include What You Use) principle. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20240325124156.3036266-1-andriy.shevchenko@linux.intel.com Signed-off-by: Guenter Roeck --- drivers/hwmon/pmbus/adp1050.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/pmbus/adp1050.c b/drivers/hwmon/pmbus/adp1050.c index 0a49bea8e13b..ea08554662d5 100644 --- a/drivers/hwmon/pmbus/adp1050.c +++ b/drivers/hwmon/pmbus/adp1050.c @@ -5,12 +5,10 @@ * Copyright (C) 2024 Analog Devices, Inc. */ #include -#include #include -#include -#include +#include #include -#include + #include "pmbus.h" static struct pmbus_driver_info adp1050_info = { -- cgit v1.2.3 From d2bc4a994a1eb34cf35615af86445d105f419192 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 25 Mar 2024 14:07:42 +0200 Subject: hwmon: (pmbus/mp2975) Replace home made version of __assign_bit() The newly introduced SWAP() macro is quite generic by naming, but moreover it's a repetition of the existing __assign_bit(). With this applied, add a missing bits.h (via now required bitops.h). Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20240325120952.3019767-2-andriy.shevchenko@linux.intel.com Signed-off-by: Guenter Roeck --- drivers/hwmon/pmbus/mp2975.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/pmbus/mp2975.c b/drivers/hwmon/pmbus/mp2975.c index 953c02a2aeb5..af118087c4ee 100644 --- a/drivers/hwmon/pmbus/mp2975.c +++ b/drivers/hwmon/pmbus/mp2975.c @@ -5,6 +5,7 @@ * Copyright (C) 2020 Nvidia Technologies Ltd. */ +#include #include #include #include @@ -396,7 +397,7 @@ static int mp2973_write_word_data(struct i2c_client *client, int page, int reg, u16 word) { u8 target, mask; - int ret; + long ret; if (reg != PMBUS_SMBALERT_MASK) return -ENODATA; @@ -415,7 +416,6 @@ static int mp2973_write_word_data(struct i2c_client *client, int page, * Set/Clear 'bit' in 'ret' based on condition followed by define for each bit in SMBALERT_MASK. * Also bit 2 & 15 are reserved. */ -#define SWAP(val, mask, cond, bit) (((mask) & (cond)) ? ((val) & ~BIT(bit)) : ((val) | BIT(bit))) #define MP2973_TEMP_OT 0 #define MP2973_VIN_UVLO 1 @@ -434,36 +434,35 @@ static int mp2973_write_word_data(struct i2c_client *client, int page, switch (target) { case PMBUS_STATUS_CML: - ret = SWAP(ret, mask, PB_CML_FAULT_INVALID_DATA, MP2973_INVALID_DATA); - ret = SWAP(ret, mask, PB_CML_FAULT_INVALID_COMMAND, MP2973_INVALID_COMMAND); - ret = SWAP(ret, mask, PB_CML_FAULT_OTHER_COMM, MP2973_OTHER_COMM); - ret = SWAP(ret, mask, PB_CML_FAULT_PACKET_ERROR, MP2973_PACKET_ERROR); + __assign_bit(MP2973_INVALID_DATA, &ret, !(mask & PB_CML_FAULT_INVALID_DATA)); + __assign_bit(MP2973_INVALID_COMMAND, &ret, !(mask & PB_CML_FAULT_INVALID_COMMAND)); + __assign_bit(MP2973_OTHER_COMM, &ret, !(mask & PB_CML_FAULT_OTHER_COMM)); + __assign_bit(MP2973_PACKET_ERROR, &ret, !(mask & PB_CML_FAULT_PACKET_ERROR)); break; case PMBUS_STATUS_VOUT: - ret = SWAP(ret, mask, PB_VOLTAGE_UV_FAULT, MP2973_VOLTAGE_UV); - ret = SWAP(ret, mask, PB_VOLTAGE_OV_FAULT, MP2973_VOLTAGE_OV); + __assign_bit(MP2973_VOLTAGE_UV, &ret, !(mask & PB_VOLTAGE_UV_FAULT)); + __assign_bit(MP2973_VOLTAGE_OV, &ret, !(mask & PB_VOLTAGE_OV_FAULT)); break; case PMBUS_STATUS_IOUT: - ret = SWAP(ret, mask, PB_IOUT_OC_FAULT, MP2973_IOUT_OC); - ret = SWAP(ret, mask, PB_IOUT_OC_LV_FAULT, MP2973_IOUT_OC_LV); + __assign_bit(MP2973_IOUT_OC, &ret, !(mask & PB_IOUT_OC_FAULT)); + __assign_bit(MP2973_IOUT_OC_LV, &ret, !(mask & PB_IOUT_OC_LV_FAULT)); break; case PMBUS_STATUS_TEMPERATURE: - ret = SWAP(ret, mask, PB_TEMP_OT_FAULT, MP2973_TEMP_OT); + __assign_bit(MP2973_TEMP_OT, &ret, !(mask & PB_TEMP_OT_FAULT)); break; /* * Map remaining bits to MFR specific to let the PMBUS core mask * those bits by default. */ case PMBUS_STATUS_MFR_SPECIFIC: - ret = SWAP(ret, mask, BIT(1), MP2973_VIN_UVLO); - ret = SWAP(ret, mask, BIT(3), MP2973_VIN_OVP); - ret = SWAP(ret, mask, BIT(4), MP2973_MTP_FAULT); - ret = SWAP(ret, mask, BIT(6), MP2973_MTP_BLK_TRIG); + __assign_bit(MP2973_VIN_UVLO, &ret, !(mask & BIT(1))); + __assign_bit(MP2973_VIN_OVP, &ret, !(mask & BIT(3))); + __assign_bit(MP2973_MTP_FAULT, &ret, !(mask & BIT(4))); + __assign_bit(MP2973_MTP_BLK_TRIG, &ret, !(mask & BIT(6))); break; default: return 0; } -#undef SWAP return pmbus_write_word_data(client, 0, PMBUS_SMBALERT_MASK, ret); } -- cgit v1.2.3 From 9050b39b2fab51231b6a68d00238e6edea950987 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 25 Mar 2024 14:07:43 +0200 Subject: hwmon: (pmbus/mp2975) Constify local pointers to pmbus_driver_info Constify the local variables pointing to "struct pmbus_driver_info" and other encoding params to annotate the function is not modifying pointed data. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20240325120952.3019767-3-andriy.shevchenko@linux.intel.com Signed-off-by: Guenter Roeck --- drivers/hwmon/pmbus/mp2975.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/pmbus/mp2975.c b/drivers/hwmon/pmbus/mp2975.c index af118087c4ee..bc7558dc87ee 100644 --- a/drivers/hwmon/pmbus/mp2975.c +++ b/drivers/hwmon/pmbus/mp2975.c @@ -942,7 +942,7 @@ mp2975_vout_per_rail_config_get(struct i2c_client *client, return 0; } -static struct pmbus_driver_info mp2975_info = { +static const struct pmbus_driver_info mp2975_info = { .pages = 1, .format[PSC_VOLTAGE_IN] = linear, .format[PSC_VOLTAGE_OUT] = direct, @@ -967,7 +967,7 @@ static struct pmbus_driver_info mp2975_info = { #endif }; -static struct pmbus_driver_info mp2973_info = { +static const struct pmbus_driver_info mp2973_info = { .pages = 1, .format[PSC_VOLTAGE_IN] = linear, .format[PSC_VOLTAGE_OUT] = direct, -- cgit v1.2.3 From 73bc2357de6cca4299eea69095a682dd09a699fe Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 25 Mar 2024 14:07:44 +0200 Subject: hwmon: (pmbus/mp2975) Use i2c_get_match_data() Use preferred i2c_get_match_data() instead of of_device_get_match_data() to get the driver match data. With this, adjust the includes to explicitly include the correct headers. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20240325120952.3019767-4-andriy.shevchenko@linux.intel.com [groeck: Dropped __maybe_unused from mp2975_of_match] Signed-off-by: Guenter Roeck --- drivers/hwmon/pmbus/mp2975.c | 56 ++++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 23 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/pmbus/mp2975.c b/drivers/hwmon/pmbus/mp2975.c index bc7558dc87ee..280bb12f762c 100644 --- a/drivers/hwmon/pmbus/mp2975.c +++ b/drivers/hwmon/pmbus/mp2975.c @@ -10,8 +10,9 @@ #include #include #include +#include #include -#include + #include "pmbus.h" /* Vendor specific registers. */ @@ -98,6 +99,11 @@ static const int mp2975_max_phases[][MP2975_PAGE_NUM] = { [mp2971] = { MP2971_MAX_PHASE_RAIL1, MP2971_MAX_PHASE_RAIL2 }, }; +struct mp2975_driver_info { + const struct pmbus_driver_info *info; + enum chips chip_id; +}; + struct mp2975_data { struct pmbus_driver_info info; enum chips chip_id; @@ -111,15 +117,6 @@ struct mp2975_data { int curr_sense_gain[MP2975_PAGE_NUM]; }; -static const struct i2c_device_id mp2975_id[] = { - {"mp2971", mp2971}, - {"mp2973", mp2973}, - {"mp2975", mp2975}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, mp2975_id); - static const struct regulator_desc __maybe_unused mp2975_reg_desc[] = { PMBUS_REGULATOR("vout", 0), PMBUS_REGULATOR("vout", 1), @@ -989,29 +986,34 @@ static const struct pmbus_driver_info mp2973_info = { #endif }; +static const struct mp2975_driver_info mp2975_ddinfo[] = { + [mp2975] = { .info = &mp2975_info, .chip_id = mp2975 }, + [mp2973] = { .info = &mp2973_info, .chip_id = mp2973 }, + [mp2971] = { .info = &mp2973_info, .chip_id = mp2971 }, +}; + static int mp2975_probe(struct i2c_client *client) { + const struct mp2975_driver_info *ddinfo; struct pmbus_driver_info *info; struct mp2975_data *data; int ret; + ddinfo = i2c_get_match_data(client); + if (!ddinfo) + return -ENODEV; + data = devm_kzalloc(&client->dev, sizeof(struct mp2975_data), GFP_KERNEL); if (!data) return -ENOMEM; - if (client->dev.of_node) - data->chip_id = (enum chips)(unsigned long)of_device_get_match_data(&client->dev); - else - data->chip_id = i2c_match_id(mp2975_id, client)->driver_data; + data->chip_id = ddinfo->chip_id; memcpy(data->max_phases, mp2975_max_phases[data->chip_id], sizeof(data->max_phases)); - if (data->chip_id == mp2975) - memcpy(&data->info, &mp2975_info, sizeof(*info)); - else - memcpy(&data->info, &mp2973_info, sizeof(*info)); + memcpy(&data->info, ddinfo->info, sizeof(data->info)); info = &data->info; @@ -1069,18 +1071,26 @@ static int mp2975_probe(struct i2c_client *client) return pmbus_do_probe(client, info); } -static const struct of_device_id __maybe_unused mp2975_of_match[] = { - {.compatible = "mps,mp2971", .data = (void *)mp2971}, - {.compatible = "mps,mp2973", .data = (void *)mp2973}, - {.compatible = "mps,mp2975", .data = (void *)mp2975}, +static const struct of_device_id mp2975_of_match[] = { + {.compatible = "mps,mp2971", .data = &mp2975_ddinfo[mp2971]}, + {.compatible = "mps,mp2973", .data = &mp2975_ddinfo[mp2973]}, + {.compatible = "mps,mp2975", .data = &mp2975_ddinfo[mp2975]}, {} }; MODULE_DEVICE_TABLE(of, mp2975_of_match); +static const struct i2c_device_id mp2975_id[] = { + {"mp2971", (kernel_ulong_t)&mp2975_ddinfo[mp2971]}, + {"mp2973", (kernel_ulong_t)&mp2975_ddinfo[mp2973]}, + {"mp2975", (kernel_ulong_t)&mp2975_ddinfo[mp2975]}, + {} +}; +MODULE_DEVICE_TABLE(i2c, mp2975_id); + static struct i2c_driver mp2975_driver = { .driver = { .name = "mp2975", - .of_match_table = of_match_ptr(mp2975_of_match), + .of_match_table = mp2975_of_match, }, .probe = mp2975_probe, .id_table = mp2975_id, -- cgit v1.2.3 From 523315a9111bf73672ba3693b5ecb3c1b47b07b2 Mon Sep 17 00:00:00 2001 From: Niklas Schnelle Date: Thu, 4 Apr 2024 14:47:00 +0200 Subject: hwmon: add HAS_IOPORT dependencies In a future patch HAS_IOPORT=n will disable inb()/outb() and friends at compile time. We thus need to add HAS_IOPORT as dependency for those drivers using them. Acked-by: Guenter Roeck Co-developed-by: Arnd Bergmann Signed-off-by: Arnd Bergmann Signed-off-by: Niklas Schnelle Link: https://lore.kernel.org/r/20240404124700.3807842-2-schnelle@linux.ibm.com Signed-off-by: Guenter Roeck --- drivers/hwmon/Kconfig | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 83945397b6eb..caacc4057e82 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -40,7 +40,7 @@ comment "Native drivers" config SENSORS_ABITUGURU tristate "Abit uGuru (rev 1 & 2)" - depends on (X86 && DMI) || COMPILE_TEST + depends on (X86 && DMI) || COMPILE_TEST && HAS_IOPORT help If you say yes here you get support for the sensor part of the first and second revision of the Abit uGuru chip. The voltage and frequency @@ -55,7 +55,7 @@ config SENSORS_ABITUGURU config SENSORS_ABITUGURU3 tristate "Abit uGuru (rev 3)" - depends on (X86 && DMI) || COMPILE_TEST + depends on (X86 && DMI) || COMPILE_TEST && HAS_IOPORT help If you say yes here you get support for the sensor part of the third revision of the Abit uGuru chip. Only reading the sensors @@ -611,6 +611,7 @@ config SENSORS_SPARX5 config SENSORS_F71805F tristate "Fintek F71805F/FG, F71806F/FG and F71872F/FG" + depends on HAS_IOPORT depends on !PPC help If you say yes here you get support for hardware monitoring @@ -622,6 +623,7 @@ config SENSORS_F71805F config SENSORS_F71882FG tristate "Fintek F71882FG and compatibles" + depends on HAS_IOPORT depends on !PPC help If you say yes here you get support for hardware monitoring @@ -854,6 +856,7 @@ config SENSORS_CORETEMP config SENSORS_IT87 tristate "ITE IT87xx and compatibles" + depends on HAS_IOPORT depends on !PPC select HWMON_VID help @@ -1561,6 +1564,7 @@ config SENSORS_LM95245 config SENSORS_PC87360 tristate "National Semiconductor PC87360 family" + depends on HAS_IOPORT depends on !PPC select HWMON_VID help @@ -1575,6 +1579,7 @@ config SENSORS_PC87360 config SENSORS_PC87427 tristate "National Semiconductor PC87427" + depends on HAS_IOPORT depends on !PPC help If you say yes here you get access to the hardware monitoring @@ -1606,6 +1611,7 @@ config SENSORS_NTC_THERMISTOR config SENSORS_NCT6683 tristate "Nuvoton NCT6683D" + depends on HAS_IOPORT depends on !PPC help If you say yes here you get support for the hardware monitoring @@ -1627,6 +1633,7 @@ config SENSORS_NCT6775_CORE config SENSORS_NCT6775 tristate "Platform driver for Nuvoton NCT6775F and compatibles" + depends on HAS_IOPORT depends on !PPC depends on ACPI || ACPI=n select HWMON_VID @@ -1883,7 +1890,7 @@ config SENSORS_SHTC1 config SENSORS_SIS5595 tristate "Silicon Integrated Systems Corp. SiS5595" - depends on PCI + depends on PCI && HAS_IOPORT help If you say yes here you get support for the integrated sensors in SiS5595 South Bridges. @@ -1903,6 +1910,7 @@ config SENSORS_SY7636A config SENSORS_DME1737 tristate "SMSC DME1737, SCH311x and compatibles" + depends on HAS_IOPORT depends on I2C && !PPC select HWMON_VID help @@ -1959,6 +1967,7 @@ config SENSORS_EMC6W201 config SENSORS_SMSC47M1 tristate "SMSC LPC47M10x and compatibles" + depends on HAS_IOPORT depends on !PPC help If you say yes here you get support for the integrated fan @@ -1993,6 +2002,7 @@ config SENSORS_SMSC47M192 config SENSORS_SMSC47B397 tristate "SMSC LPC47B397-NC" + depends on HAS_IOPORT depends on !PPC help If you say yes here you get support for the SMSC LPC47B397-NC @@ -2007,6 +2017,7 @@ config SENSORS_SCH56XX_COMMON config SENSORS_SCH5627 tristate "SMSC SCH5627" + depends on HAS_IOPORT depends on !PPC && WATCHDOG select SENSORS_SCH56XX_COMMON select WATCHDOG_CORE @@ -2020,6 +2031,7 @@ config SENSORS_SCH5627 config SENSORS_SCH5636 tristate "SMSC SCH5636" + depends on HAS_IOPORT depends on !PPC && WATCHDOG select SENSORS_SCH56XX_COMMON select WATCHDOG_CORE @@ -2272,7 +2284,7 @@ config SENSORS_VIA_CPUTEMP config SENSORS_VIA686A tristate "VIA686A" - depends on PCI + depends on PCI && HAS_IOPORT help If you say yes here you get support for the integrated sensors in Via 686A/B South Bridges. @@ -2282,6 +2294,7 @@ config SENSORS_VIA686A config SENSORS_VT1211 tristate "VIA VT1211" + depends on HAS_IOPORT depends on !PPC select HWMON_VID help @@ -2293,7 +2306,7 @@ config SENSORS_VT1211 config SENSORS_VT8231 tristate "VIA VT8231" - depends on PCI + depends on PCI && HAS_IOPORT select HWMON_VID help If you say yes here then you get support for the integrated sensors @@ -2401,6 +2414,7 @@ config SENSORS_W83L786NG config SENSORS_W83627HF tristate "Winbond W83627HF, W83627THF, W83637HF, W83687THF, W83697HF" + depends on HAS_IOPORT depends on !PPC select HWMON_VID help @@ -2413,6 +2427,7 @@ config SENSORS_W83627HF config SENSORS_W83627EHF tristate "Winbond W83627EHF/EHG/DHG/UHG, W83667HG" + depends on HAS_IOPORT depends on !PPC select HWMON_VID help -- cgit v1.2.3 From 9c871df02a17a2f569252cf7182738c2d1f453bc Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 4 Apr 2024 22:11:38 +0300 Subject: hwmon: (pwm-fan) Convert to use of_property_read_u32_array() This is a preparatory change to fulfill further conversion the driver to be OF-independent. The independent code has no analogue API that can read the value by index in the device property array. Suggested-by: Guenter Roeck Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20240404191323.3547465-2-andriy.shevchenko@linux.intel.com Signed-off-by: Guenter Roeck --- drivers/hwmon/pwm-fan.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c index b67bc9e833c0..bf902610cd07 100644 --- a/drivers/hwmon/pwm-fan.c +++ b/drivers/hwmon/pwm-fan.c @@ -25,7 +25,6 @@ struct pwm_fan_tach { int irq; atomic_t pulses; unsigned int rpm; - u8 pulses_per_revolution; }; enum pwm_fan_enable_mode { @@ -48,6 +47,7 @@ struct pwm_fan_ctx { int tach_count; struct pwm_fan_tach *tachs; + u32 *pulses_per_revolution; ktime_t sample_start; struct timer_list rpm_timer; @@ -85,7 +85,7 @@ static void sample_timer(struct timer_list *t) pulses = atomic_read(&tach->pulses); atomic_sub(pulses, &tach->pulses); tach->rpm = (unsigned int)(pulses * 1000 * 60) / - (tach->pulses_per_revolution * delta); + (ctx->pulses_per_revolution[i] * delta); } ctx->sample_start = ktime_get(); @@ -562,6 +562,20 @@ static int pwm_fan_probe(struct platform_device *pdev) if (!fan_channel_config) return -ENOMEM; ctx->fan_channel.config = fan_channel_config; + + ctx->pulses_per_revolution = devm_kmalloc_array(dev, + ctx->tach_count, + sizeof(*ctx->pulses_per_revolution), + GFP_KERNEL); + if (!ctx->pulses_per_revolution) + return -ENOMEM; + + /* Setup default pulses per revolution */ + for (i = 0; i < ctx->tach_count; i++) + ctx->pulses_per_revolution[i] = 2; + + of_property_read_u32_array(dev->of_node, "pulses-per-revolution", + ctx->pulses_per_revolution, ctx->tach_count); } channels = devm_kcalloc(dev, channel_count + 1, @@ -573,7 +587,6 @@ static int pwm_fan_probe(struct platform_device *pdev) for (i = 0; i < ctx->tach_count; i++) { struct pwm_fan_tach *tach = &ctx->tachs[i]; - u32 ppr = 2; tach->irq = platform_get_irq(pdev, i); if (tach->irq == -EPROBE_DEFER) @@ -589,12 +602,7 @@ static int pwm_fan_probe(struct platform_device *pdev) } } - of_property_read_u32_index(dev->of_node, - "pulses-per-revolution", - i, - &ppr); - tach->pulses_per_revolution = ppr; - if (!tach->pulses_per_revolution) { + if (!ctx->pulses_per_revolution[i]) { dev_err(dev, "pulses-per-revolution can't be zero.\n"); return -EINVAL; } @@ -602,7 +610,7 @@ static int pwm_fan_probe(struct platform_device *pdev) fan_channel_config[i] = HWMON_F_INPUT; dev_dbg(dev, "tach%d: irq=%d, pulses_per_revolution=%d\n", - i, tach->irq, tach->pulses_per_revolution); + i, tach->irq, ctx->pulses_per_revolution[i]); } if (ctx->tach_count > 0) { -- cgit v1.2.3 From dfd977d85b15bd69fbf39361f216feae115cd735 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 4 Apr 2024 22:11:39 +0300 Subject: hwmon: (pwm-fan) Make use of device properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert the module to be property provider agnostic and allow it to be used on non-OF platforms. Add mod_devicetable.h include. Signed-off-by: Andy Shevchenko Acked-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20240404191323.3547465-3-andriy.shevchenko@linux.intel.com Signed-off-by: Guenter Roeck --- drivers/hwmon/Kconfig | 2 +- drivers/hwmon/pwm-fan.c | 21 ++++++++++----------- 2 files changed, 11 insertions(+), 12 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index caacc4057e82..c89776d91795 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -1785,7 +1785,7 @@ config SENSORS_PT5161L config SENSORS_PWM_FAN tristate "PWM fan" - depends on (PWM && OF) || COMPILE_TEST + depends on PWM || COMPILE_TEST depends on THERMAL || THERMAL=n help If you say yes here you get support for fans connected to PWM lines. diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c index bf902610cd07..a1712649b07e 100644 --- a/drivers/hwmon/pwm-fan.c +++ b/drivers/hwmon/pwm-fan.c @@ -9,10 +9,11 @@ #include #include +#include #include #include -#include #include +#include #include #include #include @@ -421,16 +422,14 @@ static const struct thermal_cooling_device_ops pwm_fan_cooling_ops = { .set_cur_state = pwm_fan_set_cur_state, }; -static int pwm_fan_of_get_cooling_data(struct device *dev, - struct pwm_fan_ctx *ctx) +static int pwm_fan_get_cooling_data(struct device *dev, struct pwm_fan_ctx *ctx) { - struct device_node *np = dev->of_node; int num, i, ret; - if (!of_property_present(np, "cooling-levels")) + if (!device_property_present(dev, "cooling-levels")) return 0; - ret = of_property_count_u32_elems(np, "cooling-levels"); + ret = device_property_count_u32(dev, "cooling-levels"); if (ret <= 0) { dev_err(dev, "Wrong data!\n"); return ret ? : -EINVAL; @@ -442,8 +441,8 @@ static int pwm_fan_of_get_cooling_data(struct device *dev, if (!ctx->pwm_fan_cooling_levels) return -ENOMEM; - ret = of_property_read_u32_array(np, "cooling-levels", - ctx->pwm_fan_cooling_levels, num); + ret = device_property_read_u32_array(dev, "cooling-levels", + ctx->pwm_fan_cooling_levels, num); if (ret) { dev_err(dev, "Property 'cooling-levels' cannot be read!\n"); return ret; @@ -574,8 +573,8 @@ static int pwm_fan_probe(struct platform_device *pdev) for (i = 0; i < ctx->tach_count; i++) ctx->pulses_per_revolution[i] = 2; - of_property_read_u32_array(dev->of_node, "pulses-per-revolution", - ctx->pulses_per_revolution, ctx->tach_count); + device_property_read_u32_array(dev, "pulses-per-revolution", + ctx->pulses_per_revolution, ctx->tach_count); } channels = devm_kcalloc(dev, channel_count + 1, @@ -630,7 +629,7 @@ static int pwm_fan_probe(struct platform_device *pdev) return PTR_ERR(hwmon); } - ret = pwm_fan_of_get_cooling_data(dev, ctx); + ret = pwm_fan_get_cooling_data(dev, ctx); if (ret) return ret; -- cgit v1.2.3 From e27cbb607f063f79460ad520947925a2f4f9bc7c Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Tue, 9 Apr 2024 10:55:53 +0200 Subject: hwmon: (aspeed-g6-pwm-tach) Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Signed-off-by: Uwe Kleine-König Reviewed-by: Andrew Jeffery Link: https://lore.kernel.org/r/20240409085552.19868-2-u.kleine-koenig@pengutronix.de Signed-off-by: Guenter Roeck --- drivers/hwmon/aspeed-g6-pwm-tach.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/aspeed-g6-pwm-tach.c b/drivers/hwmon/aspeed-g6-pwm-tach.c index 597b3b019d49..262d46fed3aa 100644 --- a/drivers/hwmon/aspeed-g6-pwm-tach.c +++ b/drivers/hwmon/aspeed-g6-pwm-tach.c @@ -516,13 +516,11 @@ static int aspeed_pwm_tach_probe(struct platform_device *pdev) return 0; } -static int aspeed_pwm_tach_remove(struct platform_device *pdev) +static void aspeed_pwm_tach_remove(struct platform_device *pdev) { struct aspeed_pwm_tach_data *priv = platform_get_drvdata(pdev); reset_control_assert(priv->reset); - - return 0; } static const struct of_device_id aspeed_pwm_tach_match[] = { @@ -535,7 +533,7 @@ MODULE_DEVICE_TABLE(of, aspeed_pwm_tach_match); static struct platform_driver aspeed_pwm_tach_driver = { .probe = aspeed_pwm_tach_probe, - .remove = aspeed_pwm_tach_remove, + .remove_new = aspeed_pwm_tach_remove, .driver = { .name = "aspeed-g6-pwm-tach", .of_match_table = aspeed_pwm_tach_match, -- cgit v1.2.3 From f4a86616d142dd3ccff3785c0599c16571c6ef1b Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 15 Apr 2024 22:49:35 +0200 Subject: hwmon: (jc42) Remove I2C_CLASS_SPD support Last host driver supporting I2C_CLASS_SPD was i801. Now that I2C_CLASS_SPD support has been removed there, we can remove it here too. Signed-off-by: Heiner Kallweit Link: https://lore.kernel.org/r/3c4a1715-bfbb-4ae2-b35f-2f20f95e4932@gmail.com Signed-off-by: Guenter Roeck --- drivers/hwmon/jc42.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/jc42.c b/drivers/hwmon/jc42.c index 75dc25df0f8b..a00168fe569d 100644 --- a/drivers/hwmon/jc42.c +++ b/drivers/hwmon/jc42.c @@ -623,7 +623,7 @@ MODULE_DEVICE_TABLE(of, jc42_of_ids); #endif static struct i2c_driver jc42_driver = { - .class = I2C_CLASS_SPD | I2C_CLASS_HWMON, + .class = I2C_CLASS_HWMON, .driver = { .name = "jc42", .pm = JC42_DEV_PM_OPS, -- cgit v1.2.3 From f0c344c000d09e38a0240b4a6ccbcd553b18e762 Mon Sep 17 00:00:00 2001 From: Ricardo Neri Date: Thu, 25 Apr 2024 10:13:11 -0700 Subject: hwmon: (coretemp) Extend the bitmask to read temperature to 0xff The Intel Software Development manual defines the temperature digital readout as the bits [22:16] of the IA32_[PACKAGE]_THERM_STATUS registers. Bit 23 is specified as reserved. In recent processors, however, the temperature digital readout uses bits [23:16]. In those processors, using the bitmask 0x7f would lead to incorrect readings if the temperature deviates from TjMax by more than 127 degrees Celsius. Although not guaranteed, bit 23 is likely to be 0 in processors from a few generations ago. The temperature reading would still be correct in those processors when using a 0xff bitmask. Model-specific provisions can be made for older processors in which bit 23 is not 0 should the need arise. Signed-off-by: Ricardo Neri Link: https://lore.kernel.org/r/20240425171311.19519-4-ricardo.neri-calderon@linux.intel.com Signed-off-by: Guenter Roeck --- drivers/hwmon/coretemp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 616bd1a5b864..1b9203b20d70 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -411,7 +411,7 @@ static ssize_t show_temp(struct device *dev, * Return it instead of reporting an error which doesn't * really help at all. */ - tdata->temp = tjmax - ((eax >> 16) & 0x7f) * 1000; + tdata->temp = tjmax - ((eax >> 16) & 0xff) * 1000; tdata->last_updated = jiffies; } -- cgit v1.2.3 From 916300902725b362d5008ee10825a39056f0b095 Mon Sep 17 00:00:00 2001 From: Jose Ramon San Buenaventura Date: Thu, 25 Apr 2024 15:09:48 +0800 Subject: hwmon: (pmbus/adm1275) add adm1281 support Add support for adm1281 which is similar to adm1275 and other chips of the series. Signed-off-by: Jose Ramon San Buenaventura Link: https://lore.kernel.org/r/20240425070948.25788-3-jose.sanbuenaventura@analog.com Signed-off-by: Guenter Roeck --- Documentation/hwmon/adm1275.rst | 14 +++++++++++--- drivers/hwmon/pmbus/Kconfig | 4 ++-- drivers/hwmon/pmbus/adm1275.c | 7 +++++-- 3 files changed, 18 insertions(+), 7 deletions(-) (limited to 'drivers/hwmon') diff --git a/Documentation/hwmon/adm1275.rst b/Documentation/hwmon/adm1275.rst index 804590eeabdc..467daf8ce3c5 100644 --- a/Documentation/hwmon/adm1275.rst +++ b/Documentation/hwmon/adm1275.rst @@ -43,6 +43,14 @@ Supported chips: Datasheet: www.analog.com/static/imported-files/data_sheets/ADM1278.pdf + * Analog Devices ADM1281 + + Prefix: 'adm1281' + + Addresses scanned: - + + Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/adm1281.pdf + * Analog Devices ADM1293/ADM1294 Prefix: 'adm1293', 'adm1294' @@ -58,10 +66,10 @@ Description ----------- This driver supports hardware monitoring for Analog Devices ADM1075, ADM1272, -ADM1275, ADM1276, ADM1278, ADM1293, and ADM1294 Hot-Swap Controller and +ADM1275, ADM1276, ADM1278, ADM1281, ADM1293, and ADM1294 Hot-Swap Controller and Digital Power Monitors. -ADM1075, ADM1272, ADM1275, ADM1276, ADM1278, ADM1293, and ADM1294 are hot-swap +ADM1075, ADM1272, ADM1275, ADM1276, ADM1278, ADM1281, ADM1293, and ADM1294 are hot-swap controllers that allow a circuit board to be removed from or inserted into a live backplane. They also feature current and voltage readback via an integrated 12 bit analog-to-digital converter (ADC), accessed using a @@ -144,5 +152,5 @@ temp1_highest Highest observed temperature. temp1_reset_history Write any value to reset history. Temperature attributes are supported on ADM1272 and - ADM1278. + ADM1278, and ADM1281. ======================= ======================================================= diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig index 38e794d83cc3..2c727003433b 100644 --- a/drivers/hwmon/pmbus/Kconfig +++ b/drivers/hwmon/pmbus/Kconfig @@ -51,8 +51,8 @@ config SENSORS_ADM1275 tristate "Analog Devices ADM1275 and compatibles" help If you say yes here you get hardware monitoring support for Analog - Devices ADM1075, ADM1272, ADM1275, ADM1276, ADM1278, ADM1293, - and ADM1294 Hot-Swap Controller and Digital Power Monitors. + Devices ADM1075, ADM1272, ADM1275, ADM1276, ADM1278, ADM1281, + ADM1293, and ADM1294 Hot-Swap Controller and Digital Power Monitors. This driver can also be built as a module. If so, the module will be called adm1275. diff --git a/drivers/hwmon/pmbus/adm1275.c b/drivers/hwmon/pmbus/adm1275.c index e2c61d6fa521..59ffc08289bd 100644 --- a/drivers/hwmon/pmbus/adm1275.c +++ b/drivers/hwmon/pmbus/adm1275.c @@ -18,7 +18,7 @@ #include #include "pmbus.h" -enum chips { adm1075, adm1272, adm1275, adm1276, adm1278, adm1293, adm1294 }; +enum chips { adm1075, adm1272, adm1275, adm1276, adm1278, adm1281, adm1293, adm1294 }; #define ADM1275_MFR_STATUS_IOUT_WARN2 BIT(0) #define ADM1293_MFR_STATUS_VAUX_UV_WARN BIT(5) @@ -482,6 +482,7 @@ static const struct i2c_device_id adm1275_id[] = { { "adm1275", adm1275 }, { "adm1276", adm1276 }, { "adm1278", adm1278 }, + { "adm1281", adm1281 }, { "adm1293", adm1293 }, { "adm1294", adm1294 }, { } @@ -555,7 +556,8 @@ static int adm1275_probe(struct i2c_client *client) client->name, mid->name); if (mid->driver_data == adm1272 || mid->driver_data == adm1278 || - mid->driver_data == adm1293 || mid->driver_data == adm1294) + mid->driver_data == adm1281 || mid->driver_data == adm1293 || + mid->driver_data == adm1294) config_read_fn = i2c_smbus_read_word_data; else config_read_fn = i2c_smbus_read_byte_data; @@ -703,6 +705,7 @@ static int adm1275_probe(struct i2c_client *client) PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; break; case adm1278: + case adm1281: data->have_vout = true; data->have_pin_max = true; data->have_temp_max = true; -- cgit v1.2.3 From 70118f85e6538f5c376f57a3e8d621f1f3448754 Mon Sep 17 00:00:00 2001 From: David Ober Date: Thu, 28 Mar 2024 08:12:50 -0400 Subject: hwmon: Add EC Chip driver for Lenovo ThinkStation motherboards This addition adds in the ability for the system to scan the EC chip in the Lenovo ThinkStation systems to get the current fan RPM speeds the Maximum speed value for each fan also provides the CPU, DIMM other thermal statuses Signed-off-by: David Ober Link: https://lore.kernel.org/r/20240328121250.331146-1-dober6023@gmail.com [groeck: Dropped pointless case statements] [Colin King: Fixed spelling error accesssible -> accessible] Signed-off-by: Guenter Roeck --- drivers/hwmon/Kconfig | 10 + drivers/hwmon/Makefile | 1 + drivers/hwmon/lenovo-ec-sensors.c | 602 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 613 insertions(+) create mode 100644 drivers/hwmon/lenovo-ec-sensors.c (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index c89776d91795..bafc0058c728 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -917,6 +917,16 @@ config SENSORS_LAN966X This driver can also be built as a module. If so, the module will be called lan966x-hwmon. +config SENSORS_LENOVO_EC + tristate "Sensor reader for Lenovo ThinkStations" + depends on X86 + help + If you say yes here you get support for LENOVO + EC Sensor data on newer ThinkStation systems + + This driver can also be built as a module. If so, the module + will be called lenovo_ec_sensors. + config SENSORS_LINEAGE tristate "Lineage Compact Power Line Power Entry Module" depends on I2C diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 5c31808f6378..e3f25475d1f0 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -108,6 +108,7 @@ obj-$(CONFIG_SENSORS_JC42) += jc42.o obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o obj-$(CONFIG_SENSORS_K10TEMP) += k10temp.o obj-$(CONFIG_SENSORS_LAN966X) += lan966x-hwmon.o +obj-$(CONFIG_SENSORS_LENOVO_EC) += lenovo-ec-sensors.o obj-$(CONFIG_SENSORS_LINEAGE) += lineage-pem.o obj-$(CONFIG_SENSORS_LOCHNAGAR) += lochnagar-hwmon.o obj-$(CONFIG_SENSORS_LM63) += lm63.o diff --git a/drivers/hwmon/lenovo-ec-sensors.c b/drivers/hwmon/lenovo-ec-sensors.c new file mode 100644 index 000000000000..143fb79713f7 --- /dev/null +++ b/drivers/hwmon/lenovo-ec-sensors.c @@ -0,0 +1,602 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * HWMON driver for Lenovo ThinkStation based workstations + * via the embedded controller registers + * + * Copyright (C) 2024 David Ober (Lenovo) + * + * EC provides: + * - CPU temperature + * - DIMM temperature + * - Chassis zone temperatures + * - CPU fan RPM + * - DIMM fan RPM + * - Chassis fans RPM + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MCHP_SING_IDX 0x0000 +#define MCHP_EMI0_APPLICATION_ID 0x090C +#define MCHP_EMI0_EC_ADDRESS 0x0902 +#define MCHP_EMI0_EC_DATA_BYTE0 0x0904 +#define MCHP_EMI0_EC_DATA_BYTE1 0x0905 +#define MCHP_EMI0_EC_DATA_BYTE2 0x0906 +#define MCHP_EMI0_EC_DATA_BYTE3 0x0907 +#define IO_REGION_START 0x0900 +#define IO_REGION_LENGTH 0xD + +static inline u8 +get_ec_reg(unsigned char page, unsigned char index) +{ + u8 onebyte; + unsigned short m_index; + unsigned short phy_index = page * 256 + index; + + outb_p(0x01, MCHP_EMI0_APPLICATION_ID); + + m_index = phy_index & GENMASK(14, 2); + outw_p(m_index, MCHP_EMI0_EC_ADDRESS); + + onebyte = inb_p(MCHP_EMI0_EC_DATA_BYTE0 + (phy_index & GENMASK(1, 0))); + + outb_p(0x01, MCHP_EMI0_APPLICATION_ID); /* write 0x01 again to clean */ + return onebyte; +} + +enum systems { + LENOVO_PX, + LENOVO_P7, + LENOVO_P5, + LENOVO_P8, +}; + +static int px_temp_map[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + +static const char * const lenovo_px_ec_temp_label[] = { + "CPU1", + "CPU2", + "R_DIMM1", + "L_DIMM1", + "R_DIMM2", + "L_DIMM2", + "PCH", + "M2_R", + "M2_Z1R", + "M2_Z2R", + "PCI_Z1", + "PCI_Z2", + "PCI_Z3", + "PCI_Z4", + "AMB", +}; + +static int gen_temp_map[] = {0, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + +static const char * const lenovo_gen_ec_temp_label[] = { + "CPU1", + "R_DIMM", + "L_DIMM", + "PCH", + "M2_R", + "M2_Z1R", + "M2_Z2R", + "PCI_Z1", + "PCI_Z2", + "PCI_Z3", + "PCI_Z4", + "AMB", +}; + +static int px_fan_map[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + +static const char * const px_ec_fan_label[] = { + "CPU1_Fan", + "CPU2_Fan", + "Front_Fan1-1", + "Front_Fan1-2", + "Front_Fan2", + "Front_Fan3", + "MEM_Fan1", + "MEM_Fan2", + "Rear_Fan1", + "Rear_Fan2", + "Flex_Bay_Fan1", + "Flex_Bay_Fan2", + "Flex_Bay_Fan2", + "PSU_HDD_Fan", + "PSU1_Fan", + "PSU2_Fan", +}; + +static int p7_fan_map[] = {0, 2, 3, 4, 5, 6, 7, 8, 10, 11, 14}; + +static const char * const p7_ec_fan_label[] = { + "CPU1_Fan", + "HP_CPU_Fan1", + "HP_CPU_Fan2", + "PCIE1_4_Fan", + "PCIE5_7_Fan", + "MEM_Fan1", + "MEM_Fan2", + "Rear_Fan1", + "BCB_Fan", + "Flex_Bay_Fan", + "PSU_Fan", +}; + +static int p5_fan_map[] = {0, 5, 6, 7, 8, 10, 11, 14}; + +static const char * const p5_ec_fan_label[] = { + "CPU_Fan", + "HDD_Fan", + "Duct_Fan1", + "MEM_Fan", + "Rear_Fan", + "Front_Fan", + "Flex_Bay_Fan", + "PSU_Fan", +}; + +static int p8_fan_map[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14}; + +static const char * const p8_ec_fan_label[] = { + "CPU1_Fan", + "CPU2_Fan", + "HP_CPU_Fan1", + "HP_CPU_Fan2", + "PCIE1_4_Fan", + "PCIE5_7_Fan", + "DIMM1_Fan1", + "DIMM1_Fan2", + "DIMM2_Fan1", + "DIMM2_Fan2", + "Rear_Fan", + "HDD_Bay_Fan", + "Flex_Bay_Fan", + "PSU_Fan", +}; + +struct ec_sensors_data { + struct mutex mec_mutex; /* lock for sensor data access */ + const char *const *fan_labels; + const char *const *temp_labels; + const int *fan_map; + const int *temp_map; +}; + +static int +lenovo_ec_do_read_temp(struct ec_sensors_data *data, u32 attr, int channel, long *val) +{ + u8 lsb; + + switch (attr) { + case hwmon_temp_input: + mutex_lock(&data->mec_mutex); + lsb = get_ec_reg(2, 0x81 + channel); + mutex_unlock(&data->mec_mutex); + if (lsb <= 0x40) + return -ENODATA; + *val = (lsb - 0x40) * 1000; + return 0; + default: + return -EOPNOTSUPP; + } +} + +static int +lenovo_ec_do_read_fan(struct ec_sensors_data *data, u32 attr, int channel, long *val) +{ + u8 lsb, msb; + + channel *= 2; + switch (attr) { + case hwmon_fan_input: + mutex_lock(&data->mec_mutex); + lsb = get_ec_reg(4, 0x20 + channel); + msb = get_ec_reg(4, 0x21 + channel); + mutex_unlock(&data->mec_mutex); + *val = (msb << 8) + lsb; + return 0; + case hwmon_fan_max: + mutex_lock(&data->mec_mutex); + lsb = get_ec_reg(4, 0x40 + channel); + msb = get_ec_reg(4, 0x41 + channel); + mutex_unlock(&data->mec_mutex); + *val = (msb << 8) + lsb; + return 0; + default: + return -EOPNOTSUPP; + } +} + +static int +lenovo_ec_hwmon_read_string(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, const char **str) +{ + struct ec_sensors_data *state = dev_get_drvdata(dev); + + switch (type) { + case hwmon_temp: + *str = state->temp_labels[channel]; + return 0; + case hwmon_fan: + *str = state->fan_labels[channel]; + return 0; + default: + return -EOPNOTSUPP; + } +} + +static int +lenovo_ec_hwmon_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *val) +{ + struct ec_sensors_data *data = dev_get_drvdata(dev); + + switch (type) { + case hwmon_temp: + return lenovo_ec_do_read_temp(data, attr, data->temp_map[channel], val); + case hwmon_fan: + return lenovo_ec_do_read_fan(data, attr, data->fan_map[channel], val); + default: + return -EOPNOTSUPP; + } +} + +static umode_t +lenovo_ec_hwmon_is_visible(const void *data, enum hwmon_sensor_types type, + u32 attr, int channel) +{ + switch (type) { + case hwmon_temp: + if (attr == hwmon_temp_input || attr == hwmon_temp_label) + return 0444; + return 0; + case hwmon_fan: + if (attr == hwmon_fan_input || attr == hwmon_fan_max || attr == hwmon_fan_label) + return 0444; + return 0; + default: + return 0; + } +} + +static const struct hwmon_channel_info *lenovo_ec_hwmon_info_px[] = { + HWMON_CHANNEL_INFO(temp, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL), + HWMON_CHANNEL_INFO(fan, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX), + NULL +}; + +static const struct hwmon_channel_info *lenovo_ec_hwmon_info_p8[] = { + HWMON_CHANNEL_INFO(temp, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL), + HWMON_CHANNEL_INFO(fan, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX), + NULL +}; + +static const struct hwmon_channel_info *lenovo_ec_hwmon_info_p7[] = { + HWMON_CHANNEL_INFO(temp, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL), + HWMON_CHANNEL_INFO(fan, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX), + NULL +}; + +static const struct hwmon_channel_info *lenovo_ec_hwmon_info_p5[] = { + HWMON_CHANNEL_INFO(temp, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL, + HWMON_T_INPUT | HWMON_T_LABEL), + HWMON_CHANNEL_INFO(fan, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX, + HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MAX), + NULL +}; + +static const struct hwmon_ops lenovo_ec_hwmon_ops = { + .is_visible = lenovo_ec_hwmon_is_visible, + .read = lenovo_ec_hwmon_read, + .read_string = lenovo_ec_hwmon_read_string, +}; + +static struct hwmon_chip_info lenovo_ec_chip_info = { + .ops = &lenovo_ec_hwmon_ops, +}; + +static const struct dmi_system_id thinkstation_dmi_table[] = { + { + .ident = "LENOVO_PX", + .driver_data = (void *)(long)LENOVO_PX, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "30EU"), + }, + }, + { + .ident = "LENOVO_PX", + .driver_data = (void *)(long)LENOVO_PX, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "30EV"), + }, + }, + { + .ident = "LENOVO_P7", + .driver_data = (void *)(long)LENOVO_P7, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "30F2"), + }, + }, + { + .ident = "LENOVO_P7", + .driver_data = (void *)(long)LENOVO_P7, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "30F3"), + }, + }, + { + .ident = "LENOVO_P5", + .driver_data = (void *)(long)LENOVO_P5, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "30G9"), + }, + }, + { + .ident = "LENOVO_P5", + .driver_data = (void *)(long)LENOVO_P5, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "30GA"), + }, + }, + { + .ident = "LENOVO_P8", + .driver_data = (void *)(long)LENOVO_P8, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "30HH"), + }, + }, + { + .ident = "LENOVO_P8", + .driver_data = (void *)(long)LENOVO_P8, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "30HJ"), + }, + }, + {} +}; +MODULE_DEVICE_TABLE(dmi, thinkstation_dmi_table); + +static int lenovo_ec_probe(struct platform_device *pdev) +{ + struct device *hwdev; + struct ec_sensors_data *ec_data; + const struct hwmon_chip_info *chip_info; + struct device *dev = &pdev->dev; + const struct dmi_system_id *dmi_id; + int app_id; + + ec_data = devm_kzalloc(dev, sizeof(struct ec_sensors_data), GFP_KERNEL); + if (!ec_data) + return -ENOMEM; + + if (!request_region(IO_REGION_START, IO_REGION_LENGTH, "LNV-WKS")) { + pr_err(":request fail\n"); + return -EIO; + } + + dev_set_drvdata(dev, ec_data); + + chip_info = &lenovo_ec_chip_info; + + mutex_init(&ec_data->mec_mutex); + + mutex_lock(&ec_data->mec_mutex); + app_id = inb_p(MCHP_EMI0_APPLICATION_ID); + if (app_id) /* check EMI Application ID Value */ + outb_p(app_id, MCHP_EMI0_APPLICATION_ID); /* set EMI Application ID to 0 */ + outw_p(MCHP_SING_IDX, MCHP_EMI0_EC_ADDRESS); + mutex_unlock(&ec_data->mec_mutex); + + if ((inb_p(MCHP_EMI0_EC_DATA_BYTE0) != 'M') && + (inb_p(MCHP_EMI0_EC_DATA_BYTE1) != 'C') && + (inb_p(MCHP_EMI0_EC_DATA_BYTE2) != 'H') && + (inb_p(MCHP_EMI0_EC_DATA_BYTE3) != 'P')) { + release_region(IO_REGION_START, IO_REGION_LENGTH); + return -ENODEV; + } + + dmi_id = dmi_first_match(thinkstation_dmi_table); + + switch ((long)dmi_id->driver_data) { + case 0: + ec_data->fan_labels = px_ec_fan_label; + ec_data->temp_labels = lenovo_px_ec_temp_label; + ec_data->fan_map = px_fan_map; + ec_data->temp_map = px_temp_map; + lenovo_ec_chip_info.info = lenovo_ec_hwmon_info_px; + break; + case 1: + ec_data->fan_labels = p7_ec_fan_label; + ec_data->temp_labels = lenovo_gen_ec_temp_label; + ec_data->fan_map = p7_fan_map; + ec_data->temp_map = gen_temp_map; + lenovo_ec_chip_info.info = lenovo_ec_hwmon_info_p7; + break; + case 2: + ec_data->fan_labels = p5_ec_fan_label; + ec_data->temp_labels = lenovo_gen_ec_temp_label; + ec_data->fan_map = p5_fan_map; + ec_data->temp_map = gen_temp_map; + lenovo_ec_chip_info.info = lenovo_ec_hwmon_info_p5; + break; + case 3: + ec_data->fan_labels = p8_ec_fan_label; + ec_data->temp_labels = lenovo_gen_ec_temp_label; + ec_data->fan_map = p8_fan_map; + ec_data->temp_map = gen_temp_map; + lenovo_ec_chip_info.info = lenovo_ec_hwmon_info_p8; + break; + default: + release_region(IO_REGION_START, IO_REGION_LENGTH); + return -ENODEV; + } + + hwdev = devm_hwmon_device_register_with_info(dev, "lenovo_ec", + ec_data, + chip_info, NULL); + + return PTR_ERR_OR_ZERO(hwdev); +} + +static struct platform_driver lenovo_ec_sensors_platform_driver = { + .driver = { + .name = "lenovo-ec-sensors", + }, + .probe = lenovo_ec_probe, +}; + +static struct platform_device *lenovo_ec_sensors_platform_device; + +static int __init lenovo_ec_init(void) +{ + if (!dmi_check_system(thinkstation_dmi_table)) + return -ENODEV; + + lenovo_ec_sensors_platform_device = + platform_create_bundle(&lenovo_ec_sensors_platform_driver, + lenovo_ec_probe, NULL, 0, NULL, 0); + + if (IS_ERR(lenovo_ec_sensors_platform_device)) { + release_region(IO_REGION_START, IO_REGION_LENGTH); + return PTR_ERR(lenovo_ec_sensors_platform_device); + } + + return 0; +} +module_init(lenovo_ec_init); + +static void __exit lenovo_ec_exit(void) +{ + release_region(IO_REGION_START, IO_REGION_LENGTH); + platform_device_unregister(lenovo_ec_sensors_platform_device); + platform_driver_unregister(&lenovo_ec_sensors_platform_driver); +} +module_exit(lenovo_ec_exit); + +MODULE_AUTHOR("David Ober "); +MODULE_DESCRIPTION("HWMON driver for sensors accessible via EC in LENOVO motherboards"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 120584c728a69d119f5b970df17052153ad6f438 Mon Sep 17 00:00:00 2001 From: Aleksa Savic Date: Wed, 17 Apr 2024 19:50:35 +0200 Subject: hwmon: (aquacomputer_d5next) Add support for Octo flow sensor Add support for reading the flow sensor value on the Aquacomputer Octo. Implemented by David Flemstrom [1]. [1] https://github.com/aleksamagicka/aquacomputer_d5next-hwmon/pull/95 Originally-from: David Flemstrom Signed-off-by: Aleksa Savic Link: https://lore.kernel.org/r/20240417175037.32499-2-savicaleksa83@gmail.com Signed-off-by: Guenter Roeck --- Documentation/hwmon/aquacomputer_d5next.rst | 8 +++---- drivers/hwmon/aquacomputer_d5next.c | 34 ++++++++++++++++++----------- 2 files changed, 25 insertions(+), 17 deletions(-) (limited to 'drivers/hwmon') diff --git a/Documentation/hwmon/aquacomputer_d5next.rst b/Documentation/hwmon/aquacomputer_d5next.rst index cb073c79479c..f84b6a5e4373 100644 --- a/Documentation/hwmon/aquacomputer_d5next.rst +++ b/Documentation/hwmon/aquacomputer_d5next.rst @@ -45,9 +45,9 @@ seems to require sending it a complete configuration. That includes addressable RGB LEDs, for which there is no standard sysfs interface. Thus, that task is better suited for userspace tools. -The Octo exposes four physical and sixteen virtual temperature sensors, as well as -eight PWM controllable fans, along with their speed (in RPM), power, voltage and -current. +The Octo exposes four physical and sixteen virtual temperature sensors, a flow sensor +as well as eight PWM controllable fans, along with their speed (in RPM), power, voltage +and current. The Quadro exposes four physical and sixteen virtual temperature sensors, a flow sensor and four PWM controllable fans, along with their speed (in RPM), power, @@ -95,7 +95,7 @@ Sysfs entries ================ ============================================================== temp[1-20]_input Physical/virtual temperature sensors (in millidegrees Celsius) temp[1-8]_offset Temperature sensor correction offset (in millidegrees Celsius) -fan[1-8]_input Pump/fan speed (in RPM) / Flow speed (in dL/h) +fan[1-9]_input Pump/fan speed (in RPM) / Flow speed (in dL/h) fan1_min Minimal fan speed (in RPM) fan1_max Maximal fan speed (in RPM) fan1_target Target fan speed (in RPM) diff --git a/drivers/hwmon/aquacomputer_d5next.c b/drivers/hwmon/aquacomputer_d5next.c index 2efe97f8d003..166044e01921 100644 --- a/drivers/hwmon/aquacomputer_d5next.c +++ b/drivers/hwmon/aquacomputer_d5next.c @@ -202,12 +202,14 @@ static u16 aquastreamult_sensor_fan_offsets[] = { AQUASTREAMULT_FAN_OFFSET }; #define OCTO_NUM_FANS 8 #define OCTO_NUM_SENSORS 4 #define OCTO_NUM_VIRTUAL_SENSORS 16 +#define OCTO_NUM_FLOW_SENSORS 1 #define OCTO_CTRL_REPORT_SIZE 0x65F /* Sensor report offsets for the Octo */ #define OCTO_POWER_CYCLES 0x18 #define OCTO_SENSOR_START 0x3D #define OCTO_VIRTUAL_SENSORS_START 0x45 +#define OCTO_FLOW_SENSOR_OFFSET 0x7B static u16 octo_sensor_fan_offsets[] = { 0x7D, 0x8A, 0x97, 0xA4, 0xB1, 0xBE, 0xCB, 0xD8 }; /* Control report offsets for the Octo */ @@ -363,18 +365,6 @@ static const char *const label_aquaero_calc_temp_sensors[] = { "Calc. virtual sensor 4" }; -/* Labels for Octo and Quadro (except speed) */ -static const char *const label_fan_speed[] = { - "Fan 1 speed", - "Fan 2 speed", - "Fan 3 speed", - "Fan 4 speed", - "Fan 5 speed", - "Fan 6 speed", - "Fan 7 speed", - "Fan 8 speed" -}; - static const char *const label_fan_power[] = { "Fan 1 power", "Fan 2 power", @@ -408,6 +398,19 @@ static const char *const label_fan_current[] = { "Fan 8 current" }; +/* Labels for Octo fan speeds */ +static const char *const label_octo_speeds[] = { + "Fan 1 speed", + "Fan 2 speed", + "Fan 3 speed", + "Fan 4 speed", + "Fan 5 speed", + "Fan 6 speed", + "Fan 7 speed", + "Fan 8 speed", + "Flow speed [dL/h]", +}; + /* Labels for Quadro fan speeds */ static const char *const label_quadro_speeds[] = { "Fan 1 speed", @@ -844,6 +847,7 @@ static umode_t aqc_is_visible(const void *data, enum hwmon_sensor_types type, u3 return 0444; break; case aquaero: + case octo: case quadro: case highflow: /* Special case to support flow sensors */ @@ -1289,6 +1293,7 @@ static const struct hwmon_channel_info * const aqc_info[] = { HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_PULSES, 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_CHANNEL_INFO(power, HWMON_P_INPUT | HWMON_P_LABEL, @@ -1658,6 +1663,9 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id) priv->temp_sensor_start_offset = OCTO_SENSOR_START; priv->num_virtual_temp_sensors = OCTO_NUM_VIRTUAL_SENSORS; priv->virtual_temp_sensor_start_offset = OCTO_VIRTUAL_SENSORS_START; + priv->num_flow_sensors = OCTO_NUM_FLOW_SENSORS; + priv->flow_sensors_start_offset = OCTO_FLOW_SENSOR_OFFSET; + priv->temp_ctrl_offset = OCTO_TEMP_CTRL_OFFSET; priv->buffer_size = OCTO_CTRL_REPORT_SIZE; @@ -1667,7 +1675,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id) priv->temp_label = label_temp_sensors; priv->virtual_temp_label = label_virtual_temp_sensors; - priv->speed_label = label_fan_speed; + priv->speed_label = label_octo_speeds; priv->power_label = label_fan_power; priv->voltage_label = label_fan_voltage; priv->current_label = label_fan_current; -- cgit v1.2.3 From bf7b5a12bdd92b7ff6003b855b5034fb88e99e4b Mon Sep 17 00:00:00 2001 From: Aleksa Savic Date: Wed, 17 Apr 2024 19:50:36 +0200 Subject: hwmon: (aquacomputer_d5next) Add support for Octo flow sensor pulses Add support for reading and writing the flow sensor pulses on the Aquacomputer Octo. Implemented by David Flemstrom [1]. [1] https://github.com/aleksamagicka/aquacomputer_d5next-hwmon/pull/95 Originally-from: David Flemstrom Signed-off-by: Aleksa Savic Link: https://lore.kernel.org/r/20240417175037.32499-3-savicaleksa83@gmail.com Signed-off-by: Guenter Roeck --- Documentation/hwmon/aquacomputer_d5next.rst | 3 ++- drivers/hwmon/aquacomputer_d5next.c | 17 +++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) (limited to 'drivers/hwmon') diff --git a/Documentation/hwmon/aquacomputer_d5next.rst b/Documentation/hwmon/aquacomputer_d5next.rst index f84b6a5e4373..49163f387b90 100644 --- a/Documentation/hwmon/aquacomputer_d5next.rst +++ b/Documentation/hwmon/aquacomputer_d5next.rst @@ -47,7 +47,7 @@ better suited for userspace tools. The Octo exposes four physical and sixteen virtual temperature sensors, a flow sensor as well as eight PWM controllable fans, along with their speed (in RPM), power, voltage -and current. +and current. Flow sensor pulses are also available. The Quadro exposes four physical and sixteen virtual temperature sensors, a flow sensor and four PWM controllable fans, along with their speed (in RPM), power, @@ -100,6 +100,7 @@ fan1_min Minimal fan speed (in RPM) fan1_max Maximal fan speed (in RPM) fan1_target Target fan speed (in RPM) fan5_pulses Quadro flow sensor pulses +fan9_pulses Octo flow sensor pulses power[1-8]_input Pump/fan power (in micro Watts) in[0-7]_input Pump/fan voltage (in milli Volts) curr[1-8]_input Pump/fan current (in milli Amperes) diff --git a/drivers/hwmon/aquacomputer_d5next.c b/drivers/hwmon/aquacomputer_d5next.c index 166044e01921..8e55cd2f46f5 100644 --- a/drivers/hwmon/aquacomputer_d5next.c +++ b/drivers/hwmon/aquacomputer_d5next.c @@ -214,6 +214,7 @@ static u16 octo_sensor_fan_offsets[] = { 0x7D, 0x8A, 0x97, 0xA4, 0xB1, 0xBE, 0xC /* Control report offsets for the Octo */ #define OCTO_TEMP_CTRL_OFFSET 0xA +#define OCTO_FLOW_PULSES_CTRL_OFFSET 0x6 /* Fan speed offsets (0-100%) */ static u16 octo_ctrl_fan_offsets[] = { 0x5B, 0xB0, 0x105, 0x15A, 0x1AF, 0x204, 0x259, 0x2AE }; @@ -861,9 +862,16 @@ static umode_t aqc_is_visible(const void *data, enum hwmon_sensor_types type, u3 } break; case hwmon_fan_pulses: - /* Special case for Quadro flow sensor */ - if (priv->kind == quadro && channel == priv->num_fans) - return 0644; + /* Special case for Quadro/Octo flow sensor */ + if (channel == priv->num_fans) { + switch (priv->kind) { + case quadro: + case octo: + return 0644; + default: + break; + } + } break; case hwmon_fan_min: case hwmon_fan_max: @@ -1294,7 +1302,7 @@ static const struct hwmon_channel_info * const aqc_info[] = { 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_INPUT | HWMON_F_LABEL | HWMON_F_PULSES), HWMON_CHANNEL_INFO(power, HWMON_P_INPUT | HWMON_P_LABEL, HWMON_P_INPUT | HWMON_P_LABEL, @@ -1671,6 +1679,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id) priv->buffer_size = OCTO_CTRL_REPORT_SIZE; priv->ctrl_report_delay = CTRL_REPORT_DELAY; + priv->flow_pulses_ctrl_offset = OCTO_FLOW_PULSES_CTRL_OFFSET; priv->power_cycle_count_offset = OCTO_POWER_CYCLES; priv->temp_label = label_temp_sensors; -- cgit v1.2.3 From 35fe06d94e39528dad7bc646c35dfd120c0fe82a Mon Sep 17 00:00:00 2001 From: Peter Yin Date: Thu, 25 Apr 2024 23:36:01 +0800 Subject: hwmon: (pmbus) Add support for Infineon XDP710 Add support for Infineon XDP710.This is a Hot-Swap Controller. Signed-off-by: Peter Yin Link: https://lore.kernel.org/r/20240425153608.4003782-2-peteryin.openbmc@gmail.com [groeck: s/microOhmRsense/micro_ohm_osense/g; declared array static] Signed-off-by: Guenter Roeck --- Documentation/hwmon/index.rst | 1 + Documentation/hwmon/xdp710.rst | 83 ++++++++++++++++++++++++++ drivers/hwmon/pmbus/Kconfig | 9 +++ drivers/hwmon/pmbus/Makefile | 1 + drivers/hwmon/pmbus/xdp710.c | 131 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 225 insertions(+) create mode 100644 Documentation/hwmon/xdp710.rst create mode 100644 drivers/hwmon/pmbus/xdp710.c (limited to 'drivers/hwmon') diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst index 9a4fd576e6f6..03d313af469a 100644 --- a/Documentation/hwmon/index.rst +++ b/Documentation/hwmon/index.rst @@ -251,6 +251,7 @@ Hardware Monitoring Kernel Drivers wm831x wm8350 xgene-hwmon + xdp710 xdpe12284 xdpe152c4 zl6100 diff --git a/Documentation/hwmon/xdp710.rst b/Documentation/hwmon/xdp710.rst new file mode 100644 index 000000000000..083891f27818 --- /dev/null +++ b/Documentation/hwmon/xdp710.rst @@ -0,0 +1,83 @@ +.. SPDX-License-Identifier: GPL-2.0 + +Kernel driver xdp710 +==================== + +Supported chips: + + * Infineon XDP710 + + Prefix: 'xdp710' + + * Datasheet + + Publicly available at the Infineon website : https://www.infineon.com/dgdl/Infineon-XDP710-001-DataSheet-v01_00-EN.pdf?fileId=8ac78c8c8412f8d301848a5316290b97 + +Author: + + Peter Yin + +Description +----------- + +This driver implements support for Infineon XDP710 Hot-Swap Controller. + +Device compliant with: + +- PMBus rev 1.3 interface. + +Device supports direct and linear format for reading input voltage, +output voltage, output current, input power and temperature. + +The driver exports the following attributes via the 'sysfs' files +for input voltage: + +**in1_input** + +**in1_label** + +**in1_max** + +**in1_max_alarm** + +**in1_min** + +**in1_min_alarm** + +The driver provides the following attributes for output voltage: + +**in2_input** + +**in2_label** + +**in2_alarm** + +The driver provides the following attributes for output current: + +**curr1_input** + +**curr1_label** + +**curr1_alarm** + +**curr1_max** + +The driver provides the following attributes for input power: + +**power1_input** + +**power1_label** + +**power1_alarm** + +The driver provides the following attributes for temperature: + +**temp1_input** + +**temp1_max** + +**temp1_max_alarm** + +**temp1_crit** + +**temp1_crit_alarm** diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig index 2c727003433b..08e82c457356 100644 --- a/drivers/hwmon/pmbus/Kconfig +++ b/drivers/hwmon/pmbus/Kconfig @@ -521,6 +521,15 @@ config SENSORS_UCD9200 This driver can also be built as a module. If so, the module will be called ucd9200. +config SENSORS_XDP710 + tristate "Infineon XDP710 family" + help + If you say yes here you get hardware monitoring support for Infineon + XDP710. + + This driver can also be built as a module. If so, the module will + be called xdp710. + config SENSORS_XDPE152 tristate "Infineon XDPE152 family" help diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile index 95a8dea5e5ed..2279b3327bbf 100644 --- a/drivers/hwmon/pmbus/Makefile +++ b/drivers/hwmon/pmbus/Makefile @@ -52,6 +52,7 @@ obj-$(CONFIG_SENSORS_TPS53679) += tps53679.o obj-$(CONFIG_SENSORS_TPS546D24) += tps546d24.o obj-$(CONFIG_SENSORS_UCD9000) += ucd9000.o obj-$(CONFIG_SENSORS_UCD9200) += ucd9200.o +obj-$(CONFIG_SENSORS_XDP710) += xdp710.o obj-$(CONFIG_SENSORS_XDPE122) += xdpe12284.o obj-$(CONFIG_SENSORS_XDPE152) += xdpe152c4.o obj-$(CONFIG_SENSORS_ZL6100) += zl6100.o diff --git a/drivers/hwmon/pmbus/xdp710.c b/drivers/hwmon/pmbus/xdp710.c new file mode 100644 index 000000000000..03a5b937c221 --- /dev/null +++ b/drivers/hwmon/pmbus/xdp710.c @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Driver for Infineon XDP710 Hot-Swap Controller + */ + +#include +#include +#include +#include +#include "pmbus.h" + +#define XDP710_REG_CFG 0xD3 +#define XDP710_V_SNS_CFG 0xD4 +#define XDP710_CS_RNG 0xD5 + +/* + * The table to map configuration register values + * to sense resistor values + */ +static const int micro_ohm_rsense[] = { + 200, 250, 300, 330, 400, 470, 500, 600, + 670, 700, 750, 800, 900, 1000, 1100, 1200, + 1250, 1300, 1400, 1500, 1600, 1700, 1800, 1900, + 2000, 2100, 2200, 2300, 2400, 2500, 2600, 2700, + 2800, 3000, 3100, 3200, 3300, 3400, 3500, 3600, + 3700, 3800, 3900, 4000, 4100, 4200, 4300, 4400, + 4500, 4600, 4700, 4800, 4900, 5000, 5500, 6000, + 6500, 7000, 7500, 8000, 8500, 9000, 9500, 10000 +}; + +static struct pmbus_driver_info xdp710_info = { + .pages = 1, + .format[PSC_VOLTAGE_IN] = direct, + .format[PSC_VOLTAGE_OUT] = direct, + .format[PSC_CURRENT_OUT] = direct, + .format[PSC_POWER] = direct, + .format[PSC_TEMPERATURE] = direct, + .m[PSC_VOLTAGE_IN] = 4653, + .b[PSC_VOLTAGE_IN] = 0, + .R[PSC_VOLTAGE_IN] = -2, + .m[PSC_VOLTAGE_OUT] = 4653, + .b[PSC_VOLTAGE_OUT] = 0, + .R[PSC_VOLTAGE_OUT] = -2, + .m[PSC_CURRENT_OUT] = 23165, + .b[PSC_CURRENT_OUT] = 0, + .R[PSC_CURRENT_OUT] = -2, + .m[PSC_POWER] = 4211, + .b[PSC_POWER] = 0, + .R[PSC_POWER] = -2, + .m[PSC_TEMPERATURE] = 52, + .b[PSC_TEMPERATURE] = 14321, + .R[PSC_TEMPERATURE] = -1, + .func[0] = + PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_PIN | + PMBUS_HAVE_TEMP | PMBUS_HAVE_IOUT | + PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP, +}; + +static int xdp710_probe(struct i2c_client *client) +{ + struct pmbus_driver_info *info; + u8 cs_rng; + u8 vtlm_rng; + int rsense; + int ret; + int m = 0; + + info = devm_kmemdup(&client->dev, &xdp710_info, sizeof(*info), + GFP_KERNEL); + if (!info) + return -ENOMEM; + + ret = i2c_smbus_read_word_data(client, XDP710_CS_RNG); + if (ret < 0) { + dev_err(&client->dev, "Can't get CS_RNG"); + return ret; + } + cs_rng = (ret >> 6) & GENMASK(1, 0); + + ret = i2c_smbus_read_word_data(client, XDP710_V_SNS_CFG); + if (ret < 0) { + dev_err(&client->dev, "Can't get V_SNS_CFG"); + return ret; + } + vtlm_rng = ret & GENMASK(1, 0); + + ret = i2c_smbus_read_word_data(client, XDP710_REG_CFG); + if (ret < 0) { + dev_err(&client->dev, "Can't get REG_CFG"); + return ret; + } + ret &= GENMASK(5, 0); + rsense = micro_ohm_rsense[ret]; + + info->m[PSC_VOLTAGE_IN] <<= vtlm_rng; + info->m[PSC_VOLTAGE_OUT] <<= vtlm_rng; + + m = info->m[PSC_CURRENT_OUT]; + info->m[PSC_CURRENT_OUT] = DIV_ROUND_CLOSEST(m * rsense >> cs_rng, 1000); + + m = info->m[PSC_POWER]; + info->m[PSC_POWER] = DIV_ROUND_CLOSEST(m * rsense >> cs_rng, 1000); + + return pmbus_do_probe(client, info); +} + +static const struct of_device_id xdp710_of_match[] = { + { .compatible = "infineon,xdp710" }, + {} +}; + +static const struct i2c_device_id xdp710_id[] = { + {"xdp710", 0}, + { } +}; +MODULE_DEVICE_TABLE(i2c, xdp710_id); + +static struct i2c_driver xdp710_driver = { + .driver = { + .name = "xdp710", + .of_match_table = xdp710_of_match, + }, + .probe = xdp710_probe, + .id_table = xdp710_id, +}; +module_i2c_driver(xdp710_driver); + +MODULE_AUTHOR("Peter Yin "); +MODULE_DESCRIPTION("PMBus driver for XDP710 HSC"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(PMBUS); -- cgit v1.2.3 From f4f3e5de2e363892953fba10328cc2ca1e8e6ff0 Mon Sep 17 00:00:00 2001 From: Frank Crawford Date: Sun, 28 Apr 2024 16:06:33 +1000 Subject: hwmon: (it87) Rename FEAT_CONF_NOEXIT to FEAT_NOCONF as more descriptive of requirement Rename previous definitions to match the new information that they are preinitialised as enabled and should not receive codes to enter or exit configuration mode. Signed-off-by: Frank Crawford Link: https://lore.kernel.org/r/20240428060653.2425296-2-frank@crawford.emu.id.au Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index fbe86cec6055..23b68808d07d 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -320,7 +320,7 @@ struct it87_devices { * second SIO address. Never exit configuration mode on these * chips to avoid the problem. */ -#define FEAT_CONF_NOEXIT BIT(19) /* Chip should not exit conf mode */ +#define FEAT_NOCONF BIT(19) /* Chip conf mode enabled on startup */ #define FEAT_FOUR_FANS BIT(20) /* Supports four fans */ #define FEAT_FOUR_PWM BIT(21) /* Supports four fan controls */ #define FEAT_FOUR_TEMP BIT(22) @@ -452,7 +452,7 @@ static const struct it87_devices it87_devices[] = { .model = "IT8790E", .features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL - | FEAT_PWM_FREQ2 | FEAT_FANCTL_ONOFF | FEAT_CONF_NOEXIT, + | FEAT_PWM_FREQ2 | FEAT_FANCTL_ONOFF | FEAT_NOCONF, .peci_mask = 0x07, }, [it8792] = { @@ -461,7 +461,7 @@ static const struct it87_devices it87_devices[] = { .features = FEAT_NEWER_AUTOPWM | FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_TEMP_OLD_PECI | FEAT_TEMP_PECI | FEAT_10_9MV_ADC | FEAT_IN7_INTERNAL | FEAT_FANCTL_ONOFF - | FEAT_CONF_NOEXIT, + | FEAT_NOCONF, .peci_mask = 0x07, .old_peci_mask = 0x02, /* Actually reports PCH */ }, @@ -507,7 +507,7 @@ static const struct it87_devices it87_devices[] = { .features = FEAT_NEWER_AUTOPWM | FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_TEMP_OLD_PECI | FEAT_TEMP_PECI | FEAT_10_9MV_ADC | FEAT_IN7_INTERNAL | FEAT_FANCTL_ONOFF - | FEAT_CONF_NOEXIT, + | FEAT_NOCONF, .peci_mask = 0x07, .old_peci_mask = 0x02, /* Actually reports PCH */ }, @@ -544,7 +544,7 @@ static const struct it87_devices it87_devices[] = { #define has_four_temp(data) ((data)->features & FEAT_FOUR_TEMP) #define has_six_temp(data) ((data)->features & FEAT_SIX_TEMP) #define has_vin3_5v(data) ((data)->features & FEAT_VIN3_5V) -#define has_conf_noexit(data) ((data)->features & FEAT_CONF_NOEXIT) +#define has_noconf(data) ((data)->features & FEAT_NOCONF) #define has_scaling(data) ((data)->features & (FEAT_12MV_ADC | \ FEAT_10_9MV_ADC)) #define has_fanctl_onoff(data) ((data)->features & FEAT_FANCTL_ONOFF) @@ -748,7 +748,7 @@ static int smbus_disable(struct it87_data *data) superio_select(data->sioaddr, PME); superio_outb(data->sioaddr, IT87_SPECIAL_CFG_REG, data->ec_special_config & ~data->smbus_bitmap); - superio_exit(data->sioaddr, has_conf_noexit(data)); + superio_exit(data->sioaddr, has_noconf(data)); } return 0; } @@ -765,7 +765,7 @@ static int smbus_enable(struct it87_data *data) superio_select(data->sioaddr, PME); superio_outb(data->sioaddr, IT87_SPECIAL_CFG_REG, data->ec_special_config); - superio_exit(data->sioaddr, has_conf_noexit(data)); + superio_exit(data->sioaddr, has_noconf(data)); } return 0; } @@ -3143,7 +3143,7 @@ static int __init it87_find(int sioaddr, unsigned short *address, } exit: - superio_exit(sioaddr, config ? has_conf_noexit(config) : false); + superio_exit(sioaddr, config ? has_noconf(config) : false); return err; } @@ -3540,7 +3540,7 @@ static void it87_resume_sio(struct platform_device *pdev) reg2c); } - superio_exit(data->sioaddr, has_conf_noexit(data)); + superio_exit(data->sioaddr, has_noconf(data)); } static int it87_resume(struct device *dev) -- cgit v1.2.3 From e2e6a23f4bda2de9c7096aa9c310bc3400187e90 Mon Sep 17 00:00:00 2001 From: Frank Crawford Date: Sun, 28 Apr 2024 16:06:34 +1000 Subject: hwmon: (it87) Do not enter configuration mode for some chiptypes Update the configuration mode entry code to allow conditional entry, and apply to all calls. Signed-off-by: Frank Crawford Link: https://lore.kernel.org/r/20240428060653.2425296-3-frank@crawford.emu.id.au Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 23b68808d07d..702a3752a211 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -117,7 +117,7 @@ static inline void superio_select(int ioreg, int ldn) outb(ldn, ioreg + 1); } -static inline int superio_enter(int ioreg) +static inline int superio_enter(int ioreg, bool noentry) { /* * Try to reserve ioreg and ioreg + 1 for exclusive access. @@ -125,7 +125,8 @@ static inline int superio_enter(int ioreg) if (!request_muxed_region(ioreg, 2, DRVNAME)) return -EBUSY; - __superio_enter(ioreg); + if (!noentry) + __superio_enter(ioreg); return 0; } @@ -742,7 +743,7 @@ static int smbus_disable(struct it87_data *data) int err; if (data->smbus_bitmap) { - err = superio_enter(data->sioaddr); + err = superio_enter(data->sioaddr, has_noconf(data)); if (err) return err; superio_select(data->sioaddr, PME); @@ -758,7 +759,7 @@ static int smbus_enable(struct it87_data *data) int err; if (data->smbus_bitmap) { - err = superio_enter(data->sioaddr); + err = superio_enter(data->sioaddr, has_noconf(data)); if (err) return err; @@ -2674,7 +2675,7 @@ static int __init it87_find(int sioaddr, unsigned short *address, u16 chip_type; const struct it87_devices *config = NULL; - err = superio_enter(sioaddr); + err = superio_enter(sioaddr, false); if (err) return err; @@ -3520,7 +3521,7 @@ static void it87_resume_sio(struct platform_device *pdev) if (!data->need_in7_reroute) return; - err = superio_enter(data->sioaddr); + err = superio_enter(data->sioaddr, has_noconf(data)); if (err) { dev_warn(&pdev->dev, "Unable to enter Super I/O to reroute in7 (%d)", -- cgit v1.2.3 From e58095cfc55692e4da4a5e87322e09a9b75186e0 Mon Sep 17 00:00:00 2001 From: Frank Crawford Date: Sun, 28 Apr 2024 16:06:35 +1000 Subject: hwmon: (it87) Test for chipset before entering configuration mode Major part of the change for the new method to avoid chipset issues. The actual update does the following: 1) Lock the memory, but does not perform a SIO entry (previously it would have performed an SIO entry). 2) Attempt to read the chipID. This should be safe no matter which chip we have. 3) If step (2) fails, then perform SIO entry and retry chipID read. For older chips and on failure it acts similarly to prior to this patch. 4) Set the sio_data->type, similar to previously. 5) If we have not performed an SIO entry, and this is not a chip type with the NOCONF feature, then it will perform an SIO entry at this point. 6) Proceed with setup as prior to this patch. 7) Any following access to the SIO registers will invoke the SIO entry and SIO exit steps unless it is a chip with the NOCONF feature set. This was set up in the previous patches in this patchset. 8) Update to the exit based on if it had performed a SIO entry or not. Signed-off-by: Frank Crawford Link: https://lore.kernel.org/r/20240428060653.2425296-4-frank@crawford.emu.id.au [groeck: s/intialised/initialized/] Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 5 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 702a3752a211..47eeff4a692a 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -2667,6 +2667,27 @@ static const struct attribute_group it87_group_auto_pwm = { .is_visible = it87_auto_pwm_is_visible, }; +/* + * Original explanation: + * On various Gigabyte AM4 boards (AB350, AX370), the second Super-IO chip + * (IT8792E) needs to be in configuration mode before accessing the first + * due to a bug in IT8792E which otherwise results in LPC bus access errors. + * This needs to be done before accessing the first Super-IO chip since + * the second chip may have been accessed prior to loading this driver. + * + * The problem is also reported to affect IT8795E, which is used on X299 boards + * and has the same chip ID as IT8792E (0x8733). It also appears to affect + * systems with IT8790E, which is used on some Z97X-Gaming boards as well as + * Z87X-OC. + * + * From other information supplied: + * ChipIDs 0x8733, 0x8695 (early ID for IT87952E) and 0x8790 are initialized + * and left in configuration mode, and entering and/or exiting configuration + * mode is what causes the crash. + * + * The recommendation is to look up the chipID before doing any mode swap + * and then act accordingly. + */ /* SuperIO detection - will change isa_address if a chip is found */ static int __init it87_find(int sioaddr, unsigned short *address, struct it87_sio_data *sio_data, int chip_cnt) @@ -2674,16 +2695,25 @@ static int __init it87_find(int sioaddr, unsigned short *address, int err; u16 chip_type; const struct it87_devices *config = NULL; + bool enabled = false; - err = superio_enter(sioaddr, false); + /* First step, lock memory but don't enter configuration mode */ + err = superio_enter(sioaddr, true); if (err) return err; err = -ENODEV; chip_type = superio_inw(sioaddr, DEVID); - /* check first for a valid chip before forcing chip id */ - if (chip_type == 0xffff) - goto exit; + /* Check for a valid chip before forcing chip id */ + if (chip_type == 0xffff) { + /* Enter configuration mode */ + __superio_enter(sioaddr); + enabled = true; + /* and then try again */ + chip_type = superio_inw(sioaddr, DEVID); + if (chip_type == 0xffff) + goto exit; + } if (force_id_cnt == 1) { /* If only one value given use for all chips */ @@ -2767,6 +2797,18 @@ static int __init it87_find(int sioaddr, unsigned short *address, config = &it87_devices[sio_data->type]; + /* + * If previously we didn't enter configuration mode and it isn't a + * chip we know is initialised in configuration mode, then enter + * configuration mode. + * + * I don't know if any such chips can exist but be defensive. + */ + if (!enabled && !has_noconf(config)) { + __superio_enter(sioaddr); + enabled = true; + } + superio_select(sioaddr, PME); if (!(superio_inb(sioaddr, IT87_ACT_REG) & 0x01)) { pr_info("Device (chip %s ioreg 0x%x) not activated, skipping\n", @@ -3144,7 +3186,7 @@ static int __init it87_find(int sioaddr, unsigned short *address, } exit: - superio_exit(sioaddr, config ? has_noconf(config) : false); + superio_exit(sioaddr, !enabled); return err; } -- cgit v1.2.3 From 79a4c239e0a7d692520fbf4c1dc86b1fea53ea5e Mon Sep 17 00:00:00 2001 From: Frank Crawford Date: Sun, 28 Apr 2024 16:06:36 +1000 Subject: hwmon: (it87) Remove tests nolonger required Remove DMI tests for boards that are known to have issues with entering configuration mode, as now we are testing the chips directly and no longer need to rely on matching the board. Leave the DMI table in place, for the nVIDIA board, and any future expansions. Signed-off-by: Frank Crawford Link: https://lore.kernel.org/r/20240428060653.2425296-5-frank@crawford.emu.id.au Signed-off-by: Guenter Roeck --- drivers/hwmon/it87.c | 48 ------------------------------------------------ 1 file changed, 48 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 47eeff4a692a..e233aafa8856 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -3683,27 +3683,6 @@ static int it87_dmi_cb(const struct dmi_system_id *dmi_entry) return 1; } -/* - * On various Gigabyte AM4 boards (AB350, AX370), the second Super-IO chip - * (IT8792E) needs to be in configuration mode before accessing the first - * due to a bug in IT8792E which otherwise results in LPC bus access errors. - * This needs to be done before accessing the first Super-IO chip since - * the second chip may have been accessed prior to loading this driver. - * - * The problem is also reported to affect IT8795E, which is used on X299 boards - * and has the same chip ID as IT8792E (0x8733). It also appears to affect - * systems with IT8790E, which is used on some Z97X-Gaming boards as well as - * Z87X-OC. - * DMI entries for those systems will be added as they become available and - * as the problem is confirmed to affect those boards. - */ -static int it87_sio_force(const struct dmi_system_id *dmi_entry) -{ - __superio_enter(REG_4E); - - return it87_dmi_cb(dmi_entry); -}; - /* * On the Shuttle SN68PT, FAN_CTL2 is apparently not * connected to a fan, but to something else. One user @@ -3726,34 +3705,7 @@ static struct it87_dmi_data nvidia_fn68pt = { .driver_data = data, \ } -#define IT87_DMI_MATCH_GBT(name, cb, data) \ - IT87_DMI_MATCH_VND("Gigabyte Technology Co., Ltd.", name, cb, data) - static const struct dmi_system_id it87_dmi_table[] __initconst = { - IT87_DMI_MATCH_GBT("AB350", it87_sio_force, NULL), - /* ? + IT8792E/IT8795E */ - IT87_DMI_MATCH_GBT("AX370", it87_sio_force, NULL), - /* ? + IT8792E/IT8795E */ - IT87_DMI_MATCH_GBT("Z97X-Gaming G1", it87_sio_force, NULL), - /* ? + IT8790E */ - IT87_DMI_MATCH_GBT("TRX40 AORUS XTREME", it87_sio_force, NULL), - /* IT8688E + IT8792E/IT8795E */ - IT87_DMI_MATCH_GBT("Z390 AORUS ULTRA-CF", it87_sio_force, NULL), - /* IT8688E + IT8792E/IT8795E */ - IT87_DMI_MATCH_GBT("B550 AORUS PRO AC", it87_sio_force, NULL), - /* IT8688E + IT8792E/IT8795E */ - IT87_DMI_MATCH_GBT("X570 AORUS MASTER", it87_sio_force, NULL), - /* IT8688E + IT8792E/IT8795E */ - IT87_DMI_MATCH_GBT("X570 AORUS PRO", it87_sio_force, NULL), - /* IT8688E + IT8792E/IT8795E */ - IT87_DMI_MATCH_GBT("X570 AORUS PRO WIFI", it87_sio_force, NULL), - /* IT8688E + IT8792E/IT8795E */ - IT87_DMI_MATCH_GBT("X570S AERO G", it87_sio_force, NULL), - /* IT8689E + IT87952E */ - IT87_DMI_MATCH_GBT("Z690 AORUS PRO DDR4", it87_sio_force, NULL), - /* IT8689E + IT87952E */ - IT87_DMI_MATCH_GBT("Z690 AORUS PRO", it87_sio_force, NULL), - /* IT8689E + IT87952E */ IT87_DMI_MATCH_VND("nVIDIA", "FN68PT", it87_dmi_cb, &nvidia_fn68pt), { } -- cgit v1.2.3 From cbeb479ff4cd42f970e8149b18fcfd12b2180c46 Mon Sep 17 00:00:00 2001 From: Aleksa Savic Date: Sun, 28 Apr 2024 12:48:10 +0200 Subject: hwmon: (nzxt-kraken3) Decouple device names from kinds Prepare for the support of new models, for which the relationship between device name (for hwmon and debugfs) and kind (for the selection of appropriate code paths within this driver) will no longer be 1:1. Originally-from: Jonas Malaco Signed-off-by: Aleksa Savic Link: https://lore.kernel.org/r/20240428104812.14037-2-savicaleksa83@gmail.com Signed-off-by: Guenter Roeck --- drivers/hwmon/nzxt-kraken3.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/nzxt-kraken3.c b/drivers/hwmon/nzxt-kraken3.c index 5806a3f32bcb..571087e3fd3e 100644 --- a/drivers/hwmon/nzxt-kraken3.c +++ b/drivers/hwmon/nzxt-kraken3.c @@ -27,11 +27,6 @@ enum kinds { X53, Z53 } __packed; enum pwm_enable { off, manual, curve } __packed; -static const char *const kraken3_device_names[] = { - [X53] = "x53", - [Z53] = "z53", -}; - #define DRIVER_NAME "nzxt_kraken3" #define STATUS_REPORT_ID 0x75 #define FIRMWARE_REPORT_ID 0x11 @@ -849,14 +844,14 @@ static int firmware_version_show(struct seq_file *seqf, void *unused) } DEFINE_SHOW_ATTRIBUTE(firmware_version); -static void kraken3_debugfs_init(struct kraken3_data *priv) +static void kraken3_debugfs_init(struct kraken3_data *priv, const char *device_name) { char name[64]; if (!priv->firmware_version[0]) return; /* Nothing to display in debugfs */ - scnprintf(name, sizeof(name), "%s_%s-%s", DRIVER_NAME, kraken3_device_names[priv->kind], + scnprintf(name, sizeof(name), "%s_%s-%s", DRIVER_NAME, device_name, dev_name(&priv->hdev->dev)); priv->debugfs = debugfs_create_dir(name, NULL); @@ -866,6 +861,7 @@ static void kraken3_debugfs_init(struct kraken3_data *priv) static int kraken3_probe(struct hid_device *hdev, const struct hid_device_id *id) { struct kraken3_data *priv; + const char *device_name; int ret; priv = devm_kzalloc(&hdev->dev, sizeof(*priv), GFP_KERNEL); @@ -905,9 +901,11 @@ static int kraken3_probe(struct hid_device *hdev, const struct hid_device_id *id case USB_PRODUCT_ID_X53: case USB_PRODUCT_ID_X53_SECOND: priv->kind = X53; + device_name = "x53"; break; case USB_PRODUCT_ID_Z53: priv->kind = Z53; + device_name = "z53"; break; default: break; @@ -936,8 +934,7 @@ static int kraken3_probe(struct hid_device *hdev, const struct hid_device_id *id if (ret < 0) hid_warn(hdev, "fw version request failed with %d\n", ret); - priv->hwmon_dev = hwmon_device_register_with_info(&hdev->dev, - kraken3_device_names[priv->kind], priv, + priv->hwmon_dev = hwmon_device_register_with_info(&hdev->dev, device_name, priv, &kraken3_chip_info, kraken3_groups); if (IS_ERR(priv->hwmon_dev)) { ret = PTR_ERR(priv->hwmon_dev); @@ -945,7 +942,7 @@ static int kraken3_probe(struct hid_device *hdev, const struct hid_device_id *id goto fail_and_close; } - kraken3_debugfs_init(priv); + kraken3_debugfs_init(priv, device_name); return 0; -- cgit v1.2.3 From 8ec8d6c50984ca0f8ee160a9adac4b1c8f88d468 Mon Sep 17 00:00:00 2001 From: Aleksa Savic Date: Sun, 28 Apr 2024 12:48:11 +0200 Subject: hwmon: (nzxt-kraken3) Add support for NZXT Kraken 2023 (standard and Elite) models Add support for NZXT Kraken 2023 (standard) and NZXT Kraken 2023 Elite all-in-one CPU coolers. These models communicate identically to the NZXT Kraken Z-series (Z53 code paths) in all cases except when writing the fan curve, where setting additional bits in the report is needed. Reviewed-by: Jonas Malaco Signed-off-by: Aleksa Savic Link: https://lore.kernel.org/r/20240428104812.14037-3-savicaleksa83@gmail.com Signed-off-by: Guenter Roeck --- Documentation/hwmon/nzxt-kraken3.rst | 19 ++++++++++-------- drivers/hwmon/nzxt-kraken3.c | 38 ++++++++++++++++++++++++++++-------- 2 files changed, 41 insertions(+), 16 deletions(-) (limited to 'drivers/hwmon') diff --git a/Documentation/hwmon/nzxt-kraken3.rst b/Documentation/hwmon/nzxt-kraken3.rst index 90fd9dec15ff..57fe99d23301 100644 --- a/Documentation/hwmon/nzxt-kraken3.rst +++ b/Documentation/hwmon/nzxt-kraken3.rst @@ -11,17 +11,20 @@ Supported devices: * NZXT Kraken Z53 * NZXT Kraken Z63 * NZXT Kraken Z73 +* NZXT Kraken 2023 +* NZXT Kraken 2023 Elite Author: Jonas Malaco, Aleksa Savic Description ----------- -This driver enables hardware monitoring support for NZXT Kraken X53/X63/X73 and -Z53/Z63/Z73 all-in-one CPU liquid coolers. All models expose liquid temperature -and pump speed (in RPM), as well as PWM control (either as a fixed value -or through a temp-PWM curve). The Z-series models additionally expose the speed -and duty of an optionally connected fan, with the same PWM control capabilities. +This driver enables hardware monitoring support for NZXT Kraken X53/X63/X73, +Z53/Z63/Z73 and Kraken 2023 (standard and Elite) all-in-one CPU liquid coolers. +All models expose liquid temperature and pump speed (in RPM), as well as PWM +control (either as a fixed value or through a temp-PWM curve). The Z-series and +Kraken 2023 models additionally expose the speed and duty of an optionally connected +fan, with the same PWM control capabilities. Pump and fan duty control mode can be set through pwm[1-2]_enable, where 1 is for the manual control mode and 2 is for the liquid temp to PWM curve mode. @@ -39,9 +42,9 @@ The devices can report if they are faulty. The driver supports that situation and will issue a warning. This can also happen when the USB cable is connected, but SATA power is not. -The addressable RGB LEDs and LCD screen (only on Z-series models) are not -supported in this driver, but can be controlled through existing userspace tools, -such as `liquidctl`_. +The addressable RGB LEDs and LCD screen (only on Z-series and Kraken 2023 models) +are not supported in this driver, but can be controlled through existing userspace +tools, such as `liquidctl`_. .. _liquidctl: https://github.com/liquidctl/liquidctl diff --git a/drivers/hwmon/nzxt-kraken3.c b/drivers/hwmon/nzxt-kraken3.c index 571087e3fd3e..0b3f04c740b0 100644 --- a/drivers/hwmon/nzxt-kraken3.c +++ b/drivers/hwmon/nzxt-kraken3.c @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * hwmon driver for NZXT Kraken X53/X63/X73 and Z53/Z63/Z73 all in one coolers. - * X53 and Z53 in code refer to all models in their respective series (shortened - * for brevity). + * hwmon driver for NZXT Kraken X53/X63/X73, Z53/Z63/Z73 and 2023/2023 Elite all in one coolers. + * X53 and Z53 in code refer to all models in their respective series (shortened for brevity). + * 2023 models use the Z53 code paths. * * Copyright 2021 Jonas Malaco * Copyright 2022 Aleksa Savic @@ -23,8 +23,10 @@ #define USB_PRODUCT_ID_X53 0x2007 #define USB_PRODUCT_ID_X53_SECOND 0x2014 #define USB_PRODUCT_ID_Z53 0x3008 +#define USB_PRODUCT_ID_KRAKEN2023 0x300E +#define USB_PRODUCT_ID_KRAKEN2023_ELITE 0x300C -enum kinds { X53, Z53 } __packed; +enum kinds { X53, Z53, KRAKEN2023 } __packed; enum pwm_enable { off, manual, curve } __packed; #define DRIVER_NAME "nzxt_kraken3" @@ -136,6 +138,7 @@ static umode_t kraken3_is_visible(const void *data, enum hwmon_sensor_types type return 0444; break; case Z53: + case KRAKEN2023: /* Pump and fan */ if (channel < 2) return 0444; @@ -155,6 +158,7 @@ static umode_t kraken3_is_visible(const void *data, enum hwmon_sensor_types type return 0644; break; case Z53: + case KRAKEN2023: /* Pump and fan */ if (channel < 2) return 0644; @@ -242,6 +246,7 @@ static int kraken3_read_x53(struct kraken3_data *priv) return 0; } +/* Covers Z53 and KRAKEN2023 device kinds */ static int kraken3_read_z53(struct kraken3_data *priv) { int ret = mutex_lock_interruptible(&priv->z53_status_request_lock); @@ -355,6 +360,13 @@ static int kraken3_write_curve(struct kraken3_data *priv, u8 *curve_array, int c /* Set the correct ID for writing pump/fan duty (0x01 or 0x02, respectively) */ fixed_duty_cmd[SET_DUTY_ID_OFFSET] = channel + 1; + if (priv->kind == KRAKEN2023) { + /* These require 1s in the next one or two slots after SET_DUTY_ID_OFFSET */ + fixed_duty_cmd[SET_DUTY_ID_OFFSET + 1] = 1; + if (channel == 1) /* Fan */ + fixed_duty_cmd[SET_DUTY_ID_OFFSET + 2] = 1; + } + /* Copy curve to command */ memcpy(fixed_duty_cmd + SET_CURVE_DUTY_CMD_HEADER_LENGTH, curve_array, CUSTOM_CURVE_POINTS); @@ -502,8 +514,8 @@ static umode_t kraken3_curve_props_are_visible(struct kobject *kobj, struct attr struct device *dev = kobj_to_dev(kobj); struct kraken3_data *priv = dev_get_drvdata(dev); - /* Only Z53 has the fan curve */ - if (index >= CUSTOM_CURVE_POINTS && priv->kind != Z53) + /* X53 does not have a fan */ + if (index >= CUSTOM_CURVE_POINTS && priv->kind == X53) return 0; return attr->mode; @@ -769,8 +781,8 @@ static int kraken3_raw_event(struct hid_device *hdev, struct hid_report *report, if (priv->kind == X53 && !completion_done(&priv->status_report_processed)) { /* Mark first X-series device report as received */ complete_all(&priv->status_report_processed); - } else if (priv->kind == Z53) { - /* Additional readings for Z53 */ + } else if (priv->kind == Z53 || priv->kind == KRAKEN2023) { + /* Additional readings for Z53 and KRAKEN2023 */ priv->fan_input[1] = get_unaligned_le16(data + Z53_FAN_SPEED_OFFSET); priv->channel_info[1].reported_duty = kraken3_percent_to_pwm(data[Z53_FAN_DUTY_OFFSET]); @@ -907,6 +919,14 @@ static int kraken3_probe(struct hid_device *hdev, const struct hid_device_id *id priv->kind = Z53; device_name = "z53"; break; + case USB_PRODUCT_ID_KRAKEN2023: + priv->kind = KRAKEN2023; + device_name = "kraken2023"; + break; + case USB_PRODUCT_ID_KRAKEN2023_ELITE: + priv->kind = KRAKEN2023; + device_name = "kraken2023elite"; + break; default: break; } @@ -969,6 +989,8 @@ static const struct hid_device_id kraken3_table[] = { { HID_USB_DEVICE(USB_VENDOR_ID_NZXT, USB_PRODUCT_ID_X53) }, { HID_USB_DEVICE(USB_VENDOR_ID_NZXT, USB_PRODUCT_ID_X53_SECOND) }, { HID_USB_DEVICE(USB_VENDOR_ID_NZXT, USB_PRODUCT_ID_Z53) }, + { HID_USB_DEVICE(USB_VENDOR_ID_NZXT, USB_PRODUCT_ID_KRAKEN2023) }, + { HID_USB_DEVICE(USB_VENDOR_ID_NZXT, USB_PRODUCT_ID_KRAKEN2023_ELITE) }, { } }; -- cgit v1.2.3 From 801fec8df5649cdba6587522b9b3e872d31cd8c8 Mon Sep 17 00:00:00 2001 From: Delphine CC Chiu Date: Tue, 16 Apr 2024 10:22:11 +0800 Subject: hwmon: (max31790) revise the scale to write pwm Since the value for PWMOUT Target Duty Cycle register is a 9 bit left-justified value that ranges from 0 to 511 and is contained in 2 bytes. There is an issue that the PWM signal recorded by oscilloscope would not be on consistently if we set PWM to 100% to the driver. It is because the LSB of the 9 bit would always be zero if it just left shift 8 bit for the value that write to PWMOUT Target Duty Cycle register. Therefore, revise the scale of the value that was written to pwm input from 255 to 511 and modify the value to left-justified value. Signed-off-by: Delphine CC Chiu Link: https://lore.kernel.org/r/20240416022211.859483-1-Delphine_CC_Chiu@wiwynn.com Signed-off-by: Guenter Roeck --- drivers/hwmon/max31790.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/max31790.c b/drivers/hwmon/max31790.c index 3dc95196b229..7aa1aa63bf1b 100644 --- a/drivers/hwmon/max31790.c +++ b/drivers/hwmon/max31790.c @@ -49,6 +49,9 @@ #define NR_CHANNEL 6 +#define PWM_INPUT_SCALE 255 +#define MAX31790_REG_PWMOUT_SCALE 511 + /* * Client data (each client gets its own) */ @@ -343,10 +346,13 @@ static int max31790_write_pwm(struct device *dev, u32 attr, int channel, err = -EINVAL; break; } + + val = DIV_ROUND_CLOSEST(val * MAX31790_REG_PWMOUT_SCALE, + PWM_INPUT_SCALE); data->valid = false; err = i2c_smbus_write_word_swapped(client, MAX31790_REG_PWMOUT(channel), - val << 8); + val << 7); break; case hwmon_pwm_enable: fan_config = data->fan_config[channel]; -- cgit v1.2.3 From d8a66f3621c2886ad328d9df53349fc10251f583 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Tue, 30 Apr 2024 10:56:53 +0200 Subject: hwmon: Drop explicit initialization of struct i2c_device_id::driver_data to 0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These drivers don't use the driver_data member of struct i2c_device_id, so don't explicitly initialize this member. This prepares putting driver_data in an anonymous union which requires either no initialization or named designators. But it's also a nice cleanup on its own. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20240430085654.1028864-2-u.kleine-koenig@pengutronix.de Signed-off-by: Guenter Roeck --- Documentation/hwmon/pmbus.rst | 2 +- drivers/hwmon/ad7414.c | 2 +- drivers/hwmon/adc128d818.c | 2 +- drivers/hwmon/adm1026.c | 2 +- drivers/hwmon/adm1029.c | 2 +- drivers/hwmon/adm1177.c | 2 +- drivers/hwmon/adt7410.c | 4 ++-- drivers/hwmon/adt7411.c | 2 +- drivers/hwmon/adt7462.c | 2 +- drivers/hwmon/adt7470.c | 2 +- drivers/hwmon/asb100.c | 2 +- drivers/hwmon/atxp1.c | 2 +- drivers/hwmon/ds620.c | 2 +- drivers/hwmon/emc2103.c | 2 +- drivers/hwmon/emc2305.c | 8 ++++---- drivers/hwmon/emc6w201.c | 2 +- drivers/hwmon/ftsteutates.c | 2 +- drivers/hwmon/g760a.c | 2 +- drivers/hwmon/g762.c | 4 ++-- drivers/hwmon/gl518sm.c | 2 +- drivers/hwmon/gl520sm.c | 2 +- drivers/hwmon/hih6130.c | 2 +- drivers/hwmon/hs3001.c | 2 +- drivers/hwmon/ina209.c | 2 +- drivers/hwmon/ina238.c | 2 +- drivers/hwmon/ina3221.c | 2 +- drivers/hwmon/jc42.c | 2 +- drivers/hwmon/lineage-pem.c | 2 +- drivers/hwmon/lm73.c | 2 +- drivers/hwmon/lm77.c | 2 +- drivers/hwmon/lm87.c | 2 +- drivers/hwmon/lm93.c | 4 ++-- drivers/hwmon/lm95241.c | 2 +- drivers/hwmon/lm95245.c | 4 ++-- drivers/hwmon/ltc2945.c | 2 +- drivers/hwmon/ltc2947-i2c.c | 2 +- drivers/hwmon/ltc2990.c | 2 +- drivers/hwmon/ltc2991.c | 2 +- drivers/hwmon/ltc2992.c | 2 +- drivers/hwmon/ltc4151.c | 2 +- drivers/hwmon/ltc4215.c | 2 +- drivers/hwmon/ltc4222.c | 2 +- drivers/hwmon/ltc4245.c | 2 +- drivers/hwmon/ltc4260.c | 2 +- drivers/hwmon/ltc4261.c | 2 +- drivers/hwmon/max127.c | 2 +- drivers/hwmon/max1619.c | 2 +- drivers/hwmon/max31730.c | 2 +- drivers/hwmon/max31790.c | 2 +- drivers/hwmon/max6620.c | 2 +- drivers/hwmon/max6639.c | 2 +- drivers/hwmon/max6642.c | 2 +- drivers/hwmon/mc34vr500.c | 2 +- drivers/hwmon/nct7802.c | 2 +- drivers/hwmon/nct7904.c | 2 +- drivers/hwmon/pcf8591.c | 2 +- drivers/hwmon/pmbus/adm1266.c | 2 +- drivers/hwmon/pmbus/adp1050.c | 2 +- drivers/hwmon/pmbus/inspur-ipsps.c | 2 +- drivers/hwmon/pmbus/ir35221.c | 2 +- drivers/hwmon/pmbus/ir36021.c | 2 +- drivers/hwmon/pmbus/ir38064.c | 8 ++++---- drivers/hwmon/pmbus/irps5401.c | 2 +- drivers/hwmon/pmbus/lt7182s.c | 2 +- drivers/hwmon/pmbus/ltc3815.c | 2 +- drivers/hwmon/pmbus/max15301.c | 2 +- drivers/hwmon/pmbus/max16064.c | 2 +- drivers/hwmon/pmbus/max20751.c | 2 +- drivers/hwmon/pmbus/max31785.c | 6 +++--- drivers/hwmon/pmbus/max8688.c | 2 +- drivers/hwmon/pmbus/mp2888.c | 2 +- drivers/hwmon/pmbus/mp5990.c | 2 +- drivers/hwmon/pmbus/mpq8785.c | 2 +- drivers/hwmon/pmbus/pli1209bc.c | 2 +- drivers/hwmon/pmbus/pm6764tr.c | 2 +- drivers/hwmon/pmbus/pxe1610.c | 6 +++--- drivers/hwmon/pmbus/stpddc60.c | 4 ++-- drivers/hwmon/pmbus/tda38640.c | 2 +- drivers/hwmon/pmbus/tps40422.c | 2 +- drivers/hwmon/pmbus/tps546d24.c | 2 +- drivers/hwmon/pmbus/xdp710.c | 2 +- drivers/hwmon/pmbus/xdpe12284.c | 6 +++--- drivers/hwmon/pmbus/xdpe152c4.c | 4 ++-- drivers/hwmon/pt5161l.c | 2 +- drivers/hwmon/sbrmi.c | 2 +- drivers/hwmon/sbtsi_temp.c | 2 +- drivers/hwmon/sht21.c | 2 +- drivers/hwmon/sht4x.c | 2 +- drivers/hwmon/smsc47m192.c | 2 +- drivers/hwmon/stts751.c | 2 +- drivers/hwmon/tc654.c | 4 ++-- drivers/hwmon/tc74.c | 2 +- drivers/hwmon/tmp102.c | 2 +- drivers/hwmon/tmp103.c | 2 +- drivers/hwmon/tmp108.c | 2 +- drivers/hwmon/w83791d.c | 2 +- drivers/hwmon/w83792d.c | 2 +- drivers/hwmon/w83793.c | 2 +- drivers/hwmon/w83l785ts.c | 2 +- drivers/hwmon/w83l786ng.c | 2 +- 100 files changed, 119 insertions(+), 119 deletions(-) (limited to 'drivers/hwmon') diff --git a/Documentation/hwmon/pmbus.rst b/Documentation/hwmon/pmbus.rst index eb1569bfa676..d477124cf67f 100644 --- a/Documentation/hwmon/pmbus.rst +++ b/Documentation/hwmon/pmbus.rst @@ -152,7 +152,7 @@ Emerson DS1200 power modules might look as follows:: } static const struct i2c_device_id ds1200_id[] = { - {"ds1200", 0}, + {"ds1200"}, {} }; diff --git a/drivers/hwmon/ad7414.c b/drivers/hwmon/ad7414.c index 7f1bef59046f..f0b17e59827f 100644 --- a/drivers/hwmon/ad7414.c +++ b/drivers/hwmon/ad7414.c @@ -205,7 +205,7 @@ static int ad7414_probe(struct i2c_client *client) } static const struct i2c_device_id ad7414_id[] = { - { "ad7414", 0 }, + { "ad7414" }, {} }; MODULE_DEVICE_TABLE(i2c, ad7414_id); diff --git a/drivers/hwmon/adc128d818.c b/drivers/hwmon/adc128d818.c index 46e3c8c50765..8cd013d2c547 100644 --- a/drivers/hwmon/adc128d818.c +++ b/drivers/hwmon/adc128d818.c @@ -504,7 +504,7 @@ static void adc128_remove(struct i2c_client *client) } static const struct i2c_device_id adc128_id[] = { - { "adc128d818", 0 }, + { "adc128d818" }, { } }; MODULE_DEVICE_TABLE(i2c, adc128_id); diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c index 581d8edf70ea..80d09b017d3b 100644 --- a/drivers/hwmon/adm1026.c +++ b/drivers/hwmon/adm1026.c @@ -1849,7 +1849,7 @@ static int adm1026_probe(struct i2c_client *client) } static const struct i2c_device_id adm1026_id[] = { - { "adm1026", 0 }, + { "adm1026" }, { } }; MODULE_DEVICE_TABLE(i2c, adm1026_id); diff --git a/drivers/hwmon/adm1029.c b/drivers/hwmon/adm1029.c index 9a465f3f71c8..761c13092488 100644 --- a/drivers/hwmon/adm1029.c +++ b/drivers/hwmon/adm1029.c @@ -379,7 +379,7 @@ static int adm1029_probe(struct i2c_client *client) } static const struct i2c_device_id adm1029_id[] = { - { "adm1029", 0 }, + { "adm1029" }, { } }; MODULE_DEVICE_TABLE(i2c, adm1029_id); diff --git a/drivers/hwmon/adm1177.c b/drivers/hwmon/adm1177.c index 3390102d2d4a..8b2c965480e3 100644 --- a/drivers/hwmon/adm1177.c +++ b/drivers/hwmon/adm1177.c @@ -238,7 +238,7 @@ static int adm1177_probe(struct i2c_client *client) } static const struct i2c_device_id adm1177_id[] = { - {"adm1177", 0}, + {"adm1177"}, {} }; MODULE_DEVICE_TABLE(i2c, adm1177_id); diff --git a/drivers/hwmon/adt7410.c b/drivers/hwmon/adt7410.c index d15f64d4b6e7..3bf0e0a0882c 100644 --- a/drivers/hwmon/adt7410.c +++ b/drivers/hwmon/adt7410.c @@ -88,8 +88,8 @@ static int adt7410_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id adt7410_ids[] = { - { "adt7410", 0 }, - { "adt7420", 0 }, + { "adt7410" }, + { "adt7420" }, {} }; MODULE_DEVICE_TABLE(i2c, adt7410_ids); diff --git a/drivers/hwmon/adt7411.c b/drivers/hwmon/adt7411.c index 45fe4e8aae4e..08d0effd97f7 100644 --- a/drivers/hwmon/adt7411.c +++ b/drivers/hwmon/adt7411.c @@ -697,7 +697,7 @@ static int adt7411_probe(struct i2c_client *client) } static const struct i2c_device_id adt7411_id[] = { - { "adt7411", 0 }, + { "adt7411" }, { } }; MODULE_DEVICE_TABLE(i2c, adt7411_id); diff --git a/drivers/hwmon/adt7462.c b/drivers/hwmon/adt7462.c index 429566c4245d..174dfee47f7a 100644 --- a/drivers/hwmon/adt7462.c +++ b/drivers/hwmon/adt7462.c @@ -1809,7 +1809,7 @@ static int adt7462_probe(struct i2c_client *client) } static const struct i2c_device_id adt7462_id[] = { - { "adt7462", 0 }, + { "adt7462" }, { } }; MODULE_DEVICE_TABLE(i2c, adt7462_id); diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c index c4b3a4a18670..517248d2994e 100644 --- a/drivers/hwmon/adt7470.c +++ b/drivers/hwmon/adt7470.c @@ -1304,7 +1304,7 @@ static void adt7470_remove(struct i2c_client *client) } static const struct i2c_device_id adt7470_id[] = { - { "adt7470", 0 }, + { "adt7470" }, { } }; MODULE_DEVICE_TABLE(i2c, adt7470_id); diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c index 974521e9b6b4..14e7737866c2 100644 --- a/drivers/hwmon/asb100.c +++ b/drivers/hwmon/asb100.c @@ -213,7 +213,7 @@ static struct asb100_data *asb100_update_device(struct device *dev); static void asb100_init_client(struct i2c_client *client); static const struct i2c_device_id asb100_id[] = { - { "asb100", 0 }, + { "asb100" }, { } }; MODULE_DEVICE_TABLE(i2c, asb100_id); diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c index d1de020abec6..1c7e9a98b757 100644 --- a/drivers/hwmon/atxp1.c +++ b/drivers/hwmon/atxp1.c @@ -278,7 +278,7 @@ static int atxp1_probe(struct i2c_client *client) }; static const struct i2c_device_id atxp1_id[] = { - { "atxp1", 0 }, + { "atxp1" }, { } }; MODULE_DEVICE_TABLE(i2c, atxp1_id); diff --git a/drivers/hwmon/ds620.c b/drivers/hwmon/ds620.c index 4fc4df012fac..ce397042d90b 100644 --- a/drivers/hwmon/ds620.c +++ b/drivers/hwmon/ds620.c @@ -233,7 +233,7 @@ static int ds620_probe(struct i2c_client *client) } static const struct i2c_device_id ds620_id[] = { - {"ds620", 0}, + {"ds620"}, {} }; diff --git a/drivers/hwmon/emc2103.c b/drivers/hwmon/emc2103.c index b59472bbe5bf..60eddc7b0270 100644 --- a/drivers/hwmon/emc2103.c +++ b/drivers/hwmon/emc2103.c @@ -620,7 +620,7 @@ emc2103_probe(struct i2c_client *client) } static const struct i2c_device_id emc2103_ids[] = { - { "emc2103", 0, }, + { "emc2103" }, { /* LIST END */ } }; MODULE_DEVICE_TABLE(i2c, emc2103_ids); diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c index 6ef733c0be16..4d39fbd83769 100644 --- a/drivers/hwmon/emc2305.c +++ b/drivers/hwmon/emc2305.c @@ -47,10 +47,10 @@ enum emc230x_product_id { }; static const struct i2c_device_id emc2305_ids[] = { - { "emc2305", 0 }, - { "emc2303", 0 }, - { "emc2302", 0 }, - { "emc2301", 0 }, + { "emc2305" }, + { "emc2303" }, + { "emc2302" }, + { "emc2301" }, { } }; MODULE_DEVICE_TABLE(i2c, emc2305_ids); diff --git a/drivers/hwmon/emc6w201.c b/drivers/hwmon/emc6w201.c index 9a4f868bf1e6..1100c6e5daa7 100644 --- a/drivers/hwmon/emc6w201.c +++ b/drivers/hwmon/emc6w201.c @@ -464,7 +464,7 @@ static int emc6w201_probe(struct i2c_client *client) } static const struct i2c_device_id emc6w201_id[] = { - { "emc6w201", 0 }, + { "emc6w201" }, { } }; MODULE_DEVICE_TABLE(i2c, emc6w201_id); diff --git a/drivers/hwmon/ftsteutates.c b/drivers/hwmon/ftsteutates.c index b74a2665e733..a3a07662e491 100644 --- a/drivers/hwmon/ftsteutates.c +++ b/drivers/hwmon/ftsteutates.c @@ -50,7 +50,7 @@ static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END }; static const struct i2c_device_id fts_id[] = { - { "ftsteutates", 0 }, + { "ftsteutates" }, { } }; MODULE_DEVICE_TABLE(i2c, fts_id); diff --git a/drivers/hwmon/g760a.c b/drivers/hwmon/g760a.c index b5edee00267b..39ae8f826417 100644 --- a/drivers/hwmon/g760a.c +++ b/drivers/hwmon/g760a.c @@ -197,7 +197,7 @@ static int g760a_probe(struct i2c_client *client) } static const struct i2c_device_id g760a_id[] = { - { "g760a", 0 }, + { "g760a" }, { } }; MODULE_DEVICE_TABLE(i2c, g760a_id); diff --git a/drivers/hwmon/g762.c b/drivers/hwmon/g762.c index fad69ef56c75..af1228708e25 100644 --- a/drivers/hwmon/g762.c +++ b/drivers/hwmon/g762.c @@ -44,8 +44,8 @@ #define DRVNAME "g762" static const struct i2c_device_id g762_id[] = { - { "g762", 0 }, - { "g763", 0 }, + { "g762" }, + { "g763" }, { } }; MODULE_DEVICE_TABLE(i2c, g762_id); diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c index 03db6158b13a..9c68bc013950 100644 --- a/drivers/hwmon/gl518sm.c +++ b/drivers/hwmon/gl518sm.c @@ -642,7 +642,7 @@ static int gl518_probe(struct i2c_client *client) } static const struct i2c_device_id gl518_id[] = { - { "gl518sm", 0 }, + { "gl518sm" }, { } }; MODULE_DEVICE_TABLE(i2c, gl518_id); diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c index 8bbc6a4f2928..972f4f8caa2b 100644 --- a/drivers/hwmon/gl520sm.c +++ b/drivers/hwmon/gl520sm.c @@ -885,7 +885,7 @@ static int gl520_probe(struct i2c_client *client) } static const struct i2c_device_id gl520_id[] = { - { "gl520sm", 0 }, + { "gl520sm" }, { } }; MODULE_DEVICE_TABLE(i2c, gl520_id); diff --git a/drivers/hwmon/hih6130.c b/drivers/hwmon/hih6130.c index a9726b5370fb..85af8299150a 100644 --- a/drivers/hwmon/hih6130.c +++ b/drivers/hwmon/hih6130.c @@ -233,7 +233,7 @@ static int hih6130_probe(struct i2c_client *client) /* Device ID table */ static const struct i2c_device_id hih6130_id[] = { - { "hih6130", 0 }, + { "hih6130" }, { } }; MODULE_DEVICE_TABLE(i2c, hih6130_id); diff --git a/drivers/hwmon/hs3001.c b/drivers/hwmon/hs3001.c index 01ea9a3062bc..24ed3fb9a43a 100644 --- a/drivers/hwmon/hs3001.c +++ b/drivers/hwmon/hs3001.c @@ -175,7 +175,7 @@ static const struct hwmon_chip_info hs3001_chip_info = { /* device ID table */ static const struct i2c_device_id hs3001_ids[] = { - { "hs3001", 0 }, + { "hs3001" }, { }, }; diff --git a/drivers/hwmon/ina209.c b/drivers/hwmon/ina209.c index d9b57a4b3e41..bd7b3380d847 100644 --- a/drivers/hwmon/ina209.c +++ b/drivers/hwmon/ina209.c @@ -576,7 +576,7 @@ static void ina209_remove(struct i2c_client *client) } static const struct i2c_device_id ina209_id[] = { - { "ina209", 0 }, + { "ina209" }, { } }; MODULE_DEVICE_TABLE(i2c, ina209_id); diff --git a/drivers/hwmon/ina238.c b/drivers/hwmon/ina238.c index 69289293bc38..855626f1bc01 100644 --- a/drivers/hwmon/ina238.c +++ b/drivers/hwmon/ina238.c @@ -616,7 +616,7 @@ static int ina238_probe(struct i2c_client *client) } static const struct i2c_device_id ina238_id[] = { - { "ina238", 0 }, + { "ina238" }, { } }; MODULE_DEVICE_TABLE(i2c, ina238_id); diff --git a/drivers/hwmon/ina3221.c b/drivers/hwmon/ina3221.c index 2c9530b6f192..f0053f87e3e6 100644 --- a/drivers/hwmon/ina3221.c +++ b/drivers/hwmon/ina3221.c @@ -1031,7 +1031,7 @@ static const struct of_device_id ina3221_of_match_table[] = { MODULE_DEVICE_TABLE(of, ina3221_of_match_table); static const struct i2c_device_id ina3221_ids[] = { - { "ina3221", 0 }, + { "ina3221" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(i2c, ina3221_ids); diff --git a/drivers/hwmon/jc42.c b/drivers/hwmon/jc42.c index a00168fe569d..7092f8f025b8 100644 --- a/drivers/hwmon/jc42.c +++ b/drivers/hwmon/jc42.c @@ -609,7 +609,7 @@ static const struct dev_pm_ops jc42_dev_pm_ops = { #endif /* CONFIG_PM */ static const struct i2c_device_id jc42_id[] = { - { "jc42", 0 }, + { "jc42" }, { } }; MODULE_DEVICE_TABLE(i2c, jc42_id); diff --git a/drivers/hwmon/lineage-pem.c b/drivers/hwmon/lineage-pem.c index df69c380cde7..64a335a64a2e 100644 --- a/drivers/hwmon/lineage-pem.c +++ b/drivers/hwmon/lineage-pem.c @@ -502,7 +502,7 @@ static int pem_probe(struct i2c_client *client) } static const struct i2c_device_id pem_id[] = { - {"lineage_pem", 0}, + {"lineage_pem"}, {} }; MODULE_DEVICE_TABLE(i2c, pem_id); diff --git a/drivers/hwmon/lm73.c b/drivers/hwmon/lm73.c index 637d35c5ae23..581b01572e1b 100644 --- a/drivers/hwmon/lm73.c +++ b/drivers/hwmon/lm73.c @@ -220,7 +220,7 @@ lm73_probe(struct i2c_client *client) } static const struct i2c_device_id lm73_ids[] = { - { "lm73", 0 }, + { "lm73" }, { /* LIST END */ } }; MODULE_DEVICE_TABLE(i2c, lm73_ids); diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c index 8b9862519178..80f7a6a3f9a2 100644 --- a/drivers/hwmon/lm77.c +++ b/drivers/hwmon/lm77.c @@ -337,7 +337,7 @@ static int lm77_probe(struct i2c_client *client) } static const struct i2c_device_id lm77_id[] = { - { "lm77", 0 }, + { "lm77" }, { } }; MODULE_DEVICE_TABLE(i2c, lm77_id); diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c index 2195a735d28e..03964127a12a 100644 --- a/drivers/hwmon/lm87.c +++ b/drivers/hwmon/lm87.c @@ -975,7 +975,7 @@ static int lm87_probe(struct i2c_client *client) */ static const struct i2c_device_id lm87_id[] = { - { "lm87", 0 }, + { "lm87" }, { "adm1024", 0 }, { } }; diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c index 75bca805720e..be4853fad80f 100644 --- a/drivers/hwmon/lm93.c +++ b/drivers/hwmon/lm93.c @@ -2624,8 +2624,8 @@ static int lm93_probe(struct i2c_client *client) } static const struct i2c_device_id lm93_id[] = { - { "lm93", 0 }, - { "lm94", 0 }, + { "lm93" }, + { "lm94" }, { } }; MODULE_DEVICE_TABLE(i2c, lm93_id); diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c index 475551f5024b..4ad69a2de105 100644 --- a/drivers/hwmon/lm95241.c +++ b/drivers/hwmon/lm95241.c @@ -457,7 +457,7 @@ static int lm95241_probe(struct i2c_client *client) /* Driver data (common to all clients) */ static const struct i2c_device_id lm95241_id[] = { - { "lm95231", 0 }, + { "lm95231" }, { "lm95241", 0 }, { } }; diff --git a/drivers/hwmon/lm95245.c b/drivers/hwmon/lm95245.c index 17ff54bd4015..d293b4f15dc1 100644 --- a/drivers/hwmon/lm95245.c +++ b/drivers/hwmon/lm95245.c @@ -578,8 +578,8 @@ static int lm95245_probe(struct i2c_client *client) /* Driver data (common to all clients) */ static const struct i2c_device_id lm95245_id[] = { - { "lm95235", 0 }, - { "lm95245", 0 }, + { "lm95235" }, + { "lm95245" }, { } }; MODULE_DEVICE_TABLE(i2c, lm95245_id); diff --git a/drivers/hwmon/ltc2945.c b/drivers/hwmon/ltc2945.c index 45b87a863cae..3e0e0e0687bd 100644 --- a/drivers/hwmon/ltc2945.c +++ b/drivers/hwmon/ltc2945.c @@ -508,7 +508,7 @@ static int ltc2945_probe(struct i2c_client *client) } static const struct i2c_device_id ltc2945_id[] = { - {"ltc2945", 0}, + {"ltc2945"}, { } }; diff --git a/drivers/hwmon/ltc2947-i2c.c b/drivers/hwmon/ltc2947-i2c.c index 33f574bf2ce7..176d710706dd 100644 --- a/drivers/hwmon/ltc2947-i2c.c +++ b/drivers/hwmon/ltc2947-i2c.c @@ -27,7 +27,7 @@ static int ltc2947_probe(struct i2c_client *i2c) } static const struct i2c_device_id ltc2947_id[] = { - {"ltc2947", 0}, + {"ltc2947"}, {} }; MODULE_DEVICE_TABLE(i2c, ltc2947_id); diff --git a/drivers/hwmon/ltc2990.c b/drivers/hwmon/ltc2990.c index 1ad362c0fd2c..f1c1933c52cf 100644 --- a/drivers/hwmon/ltc2990.c +++ b/drivers/hwmon/ltc2990.c @@ -259,7 +259,7 @@ static int ltc2990_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id ltc2990_i2c_id[] = { - { "ltc2990", 0 }, + { "ltc2990" }, {} }; MODULE_DEVICE_TABLE(i2c, ltc2990_i2c_id); diff --git a/drivers/hwmon/ltc2991.c b/drivers/hwmon/ltc2991.c index 80a6e391f266..06750bb93c23 100644 --- a/drivers/hwmon/ltc2991.c +++ b/drivers/hwmon/ltc2991.c @@ -414,7 +414,7 @@ static const struct of_device_id ltc2991_of_match[] = { MODULE_DEVICE_TABLE(of, ltc2991_of_match); static const struct i2c_device_id ltc2991_i2c_id[] = { - { "ltc2991", 0 }, + { "ltc2991" }, {} }; MODULE_DEVICE_TABLE(i2c, ltc2991_i2c_id); diff --git a/drivers/hwmon/ltc2992.c b/drivers/hwmon/ltc2992.c index 001799bc28ed..229aed15d5ca 100644 --- a/drivers/hwmon/ltc2992.c +++ b/drivers/hwmon/ltc2992.c @@ -922,7 +922,7 @@ static const struct of_device_id ltc2992_of_match[] = { MODULE_DEVICE_TABLE(of, ltc2992_of_match); static const struct i2c_device_id ltc2992_i2c_id[] = { - {"ltc2992", 0}, + {"ltc2992"}, {} }; MODULE_DEVICE_TABLE(i2c, ltc2992_i2c_id); diff --git a/drivers/hwmon/ltc4151.c b/drivers/hwmon/ltc4151.c index f42ac3c9475e..fa66eda78efe 100644 --- a/drivers/hwmon/ltc4151.c +++ b/drivers/hwmon/ltc4151.c @@ -188,7 +188,7 @@ static int ltc4151_probe(struct i2c_client *client) } static const struct i2c_device_id ltc4151_id[] = { - { "ltc4151", 0 }, + { "ltc4151" }, { } }; MODULE_DEVICE_TABLE(i2c, ltc4151_id); diff --git a/drivers/hwmon/ltc4215.c b/drivers/hwmon/ltc4215.c index 66fd28f713ab..cce452711cec 100644 --- a/drivers/hwmon/ltc4215.c +++ b/drivers/hwmon/ltc4215.c @@ -245,7 +245,7 @@ static int ltc4215_probe(struct i2c_client *client) } static const struct i2c_device_id ltc4215_id[] = { - { "ltc4215", 0 }, + { "ltc4215" }, { } }; MODULE_DEVICE_TABLE(i2c, ltc4215_id); diff --git a/drivers/hwmon/ltc4222.c b/drivers/hwmon/ltc4222.c index 9098ef521739..f7eb007fd766 100644 --- a/drivers/hwmon/ltc4222.c +++ b/drivers/hwmon/ltc4222.c @@ -200,7 +200,7 @@ static int ltc4222_probe(struct i2c_client *client) } static const struct i2c_device_id ltc4222_id[] = { - {"ltc4222", 0}, + {"ltc4222"}, { } }; diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c index b90184a3e0ec..14593bc81e85 100644 --- a/drivers/hwmon/ltc4245.c +++ b/drivers/hwmon/ltc4245.c @@ -469,7 +469,7 @@ static int ltc4245_probe(struct i2c_client *client) } static const struct i2c_device_id ltc4245_id[] = { - { "ltc4245", 0 }, + { "ltc4245" }, { } }; MODULE_DEVICE_TABLE(i2c, ltc4245_id); diff --git a/drivers/hwmon/ltc4260.c b/drivers/hwmon/ltc4260.c index 52f7a809b27b..9750dc9aa336 100644 --- a/drivers/hwmon/ltc4260.c +++ b/drivers/hwmon/ltc4260.c @@ -163,7 +163,7 @@ static int ltc4260_probe(struct i2c_client *client) } static const struct i2c_device_id ltc4260_id[] = { - {"ltc4260", 0}, + {"ltc4260"}, { } }; diff --git a/drivers/hwmon/ltc4261.c b/drivers/hwmon/ltc4261.c index 509e68176c7a..2cd218a6a3be 100644 --- a/drivers/hwmon/ltc4261.c +++ b/drivers/hwmon/ltc4261.c @@ -222,7 +222,7 @@ static int ltc4261_probe(struct i2c_client *client) } static const struct i2c_device_id ltc4261_id[] = { - {"ltc4261", 0}, + {"ltc4261"}, {} }; diff --git a/drivers/hwmon/max127.c b/drivers/hwmon/max127.c index da2289e3560a..a9aab8862f5e 100644 --- a/drivers/hwmon/max127.c +++ b/drivers/hwmon/max127.c @@ -329,7 +329,7 @@ static int max127_probe(struct i2c_client *client) } static const struct i2c_device_id max127_id[] = { - { "max127", 0 }, + { "max127" }, { } }; MODULE_DEVICE_TABLE(i2c, max127_id); diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c index 500dc926a7a7..a89a519cf5d9 100644 --- a/drivers/hwmon/max1619.c +++ b/drivers/hwmon/max1619.c @@ -285,7 +285,7 @@ static int max1619_probe(struct i2c_client *new_client) } static const struct i2c_device_id max1619_id[] = { - { "max1619", 0 }, + { "max1619" }, { } }; MODULE_DEVICE_TABLE(i2c, max1619_id); diff --git a/drivers/hwmon/max31730.c b/drivers/hwmon/max31730.c index 7d237db6e57c..2f4b419b6c9e 100644 --- a/drivers/hwmon/max31730.c +++ b/drivers/hwmon/max31730.c @@ -345,7 +345,7 @@ max31730_probe(struct i2c_client *client) } static const struct i2c_device_id max31730_ids[] = { - { "max31730", 0, }, + { "max31730" }, { } }; MODULE_DEVICE_TABLE(i2c, max31730_ids); diff --git a/drivers/hwmon/max31790.c b/drivers/hwmon/max31790.c index 7aa1aa63bf1b..f56913327004 100644 --- a/drivers/hwmon/max31790.c +++ b/drivers/hwmon/max31790.c @@ -543,7 +543,7 @@ static int max31790_probe(struct i2c_client *client) } static const struct i2c_device_id max31790_id[] = { - { "max31790", 0 }, + { "max31790" }, { } }; MODULE_DEVICE_TABLE(i2c, max31790_id); diff --git a/drivers/hwmon/max6620.c b/drivers/hwmon/max6620.c index 5d12fb9c9786..13201fb755c9 100644 --- a/drivers/hwmon/max6620.c +++ b/drivers/hwmon/max6620.c @@ -493,7 +493,7 @@ static int max6620_probe(struct i2c_client *client) } static const struct i2c_device_id max6620_id[] = { - { "max6620", 0 }, + { "max6620" }, { } }; MODULE_DEVICE_TABLE(i2c, max6620_id); diff --git a/drivers/hwmon/max6639.c b/drivers/hwmon/max6639.c index aa7f21ab2395..5dd0349e8bd0 100644 --- a/drivers/hwmon/max6639.c +++ b/drivers/hwmon/max6639.c @@ -610,7 +610,7 @@ static int max6639_resume(struct device *dev) } static const struct i2c_device_id max6639_id[] = { - {"max6639", 0}, + {"max6639"}, { } }; diff --git a/drivers/hwmon/max6642.c b/drivers/hwmon/max6642.c index 8b2e4d6101a2..9302ab233910 100644 --- a/drivers/hwmon/max6642.c +++ b/drivers/hwmon/max6642.c @@ -291,7 +291,7 @@ static int max6642_probe(struct i2c_client *client) */ static const struct i2c_device_id max6642_id[] = { - { "max6642", 0 }, + { "max6642" }, { } }; MODULE_DEVICE_TABLE(i2c, max6642_id); diff --git a/drivers/hwmon/mc34vr500.c b/drivers/hwmon/mc34vr500.c index 0c8fd3fce83e..84458e4533d8 100644 --- a/drivers/hwmon/mc34vr500.c +++ b/drivers/hwmon/mc34vr500.c @@ -235,7 +235,7 @@ static int mc34vr500_probe(struct i2c_client *client) } static const struct i2c_device_id mc34vr500_id[] = { - { "mc34vr500", 0 }, + { "mc34vr500" }, { }, }; MODULE_DEVICE_TABLE(i2c, mc34vr500_id); diff --git a/drivers/hwmon/nct7802.c b/drivers/hwmon/nct7802.c index a0e664d5ebfe..97e8c6424403 100644 --- a/drivers/hwmon/nct7802.c +++ b/drivers/hwmon/nct7802.c @@ -1212,7 +1212,7 @@ static const unsigned short nct7802_address_list[] = { }; static const struct i2c_device_id nct7802_idtable[] = { - { "nct7802", 0 }, + { "nct7802" }, { } }; MODULE_DEVICE_TABLE(i2c, nct7802_idtable); diff --git a/drivers/hwmon/nct7904.c b/drivers/hwmon/nct7904.c index 8f867d4570e1..f1e6eda949ba 100644 --- a/drivers/hwmon/nct7904.c +++ b/drivers/hwmon/nct7904.c @@ -1161,7 +1161,7 @@ static int nct7904_probe(struct i2c_client *client) } static const struct i2c_device_id nct7904_id[] = { - {"nct7904", 0}, + {"nct7904"}, {} }; MODULE_DEVICE_TABLE(i2c, nct7904_id); diff --git a/drivers/hwmon/pcf8591.c b/drivers/hwmon/pcf8591.c index 66c76b28c9e0..167d2fe4d543 100644 --- a/drivers/hwmon/pcf8591.c +++ b/drivers/hwmon/pcf8591.c @@ -285,7 +285,7 @@ static int pcf8591_read_channel(struct device *dev, int channel) } static const struct i2c_device_id pcf8591_id[] = { - { "pcf8591", 0 }, + { "pcf8591" }, { } }; MODULE_DEVICE_TABLE(i2c, pcf8591_id); diff --git a/drivers/hwmon/pmbus/adm1266.c b/drivers/hwmon/pmbus/adm1266.c index ed0a7b9fae4b..2c4d94cc8729 100644 --- a/drivers/hwmon/pmbus/adm1266.c +++ b/drivers/hwmon/pmbus/adm1266.c @@ -490,7 +490,7 @@ static const struct of_device_id adm1266_of_match[] = { MODULE_DEVICE_TABLE(of, adm1266_of_match); static const struct i2c_device_id adm1266_id[] = { - { "adm1266", 0 }, + { "adm1266" }, { } }; MODULE_DEVICE_TABLE(i2c, adm1266_id); diff --git a/drivers/hwmon/pmbus/adp1050.c b/drivers/hwmon/pmbus/adp1050.c index ea08554662d5..20f22730fc01 100644 --- a/drivers/hwmon/pmbus/adp1050.c +++ b/drivers/hwmon/pmbus/adp1050.c @@ -29,7 +29,7 @@ static int adp1050_probe(struct i2c_client *client) } static const struct i2c_device_id adp1050_id[] = { - {"adp1050", 0}, + {"adp1050"}, {} }; MODULE_DEVICE_TABLE(i2c, adp1050_id); diff --git a/drivers/hwmon/pmbus/inspur-ipsps.c b/drivers/hwmon/pmbus/inspur-ipsps.c index dfeae68b5e52..3e3cc9a0f116 100644 --- a/drivers/hwmon/pmbus/inspur-ipsps.c +++ b/drivers/hwmon/pmbus/inspur-ipsps.c @@ -197,7 +197,7 @@ static int ipsps_probe(struct i2c_client *client) } static const struct i2c_device_id ipsps_id[] = { - { "ipsps1", 0 }, + { "ipsps1" }, {} }; MODULE_DEVICE_TABLE(i2c, ipsps_id); diff --git a/drivers/hwmon/pmbus/ir35221.c b/drivers/hwmon/pmbus/ir35221.c index e3ee5c1bd967..503be59c6c7f 100644 --- a/drivers/hwmon/pmbus/ir35221.c +++ b/drivers/hwmon/pmbus/ir35221.c @@ -126,7 +126,7 @@ static int ir35221_probe(struct i2c_client *client) } static const struct i2c_device_id ir35221_id[] = { - {"ir35221", 0}, + {"ir35221"}, {} }; diff --git a/drivers/hwmon/pmbus/ir36021.c b/drivers/hwmon/pmbus/ir36021.c index a263afeb8ac1..5148c9187c9e 100644 --- a/drivers/hwmon/pmbus/ir36021.c +++ b/drivers/hwmon/pmbus/ir36021.c @@ -51,7 +51,7 @@ static int ir36021_probe(struct i2c_client *client) } static const struct i2c_device_id ir36021_id[] = { - { "ir36021", 0 }, + { "ir36021" }, {}, }; MODULE_DEVICE_TABLE(i2c, ir36021_id); diff --git a/drivers/hwmon/pmbus/ir38064.c b/drivers/hwmon/pmbus/ir38064.c index 69e18cb468f6..d4bcc9c39774 100644 --- a/drivers/hwmon/pmbus/ir38064.c +++ b/drivers/hwmon/pmbus/ir38064.c @@ -53,10 +53,10 @@ static int ir38064_probe(struct i2c_client *client) } static const struct i2c_device_id ir38064_id[] = { - {"ir38060", 0}, - {"ir38064", 0}, - {"ir38164", 0}, - {"ir38263", 0}, + {"ir38060"}, + {"ir38064"}, + {"ir38164"}, + {"ir38263"}, {} }; diff --git a/drivers/hwmon/pmbus/irps5401.c b/drivers/hwmon/pmbus/irps5401.c index 146d32a35a7c..f0bdf55c95bf 100644 --- a/drivers/hwmon/pmbus/irps5401.c +++ b/drivers/hwmon/pmbus/irps5401.c @@ -44,7 +44,7 @@ static int irps5401_probe(struct i2c_client *client) } static const struct i2c_device_id irps5401_id[] = { - {"irps5401", 0}, + {"irps5401"}, {} }; diff --git a/drivers/hwmon/pmbus/lt7182s.c b/drivers/hwmon/pmbus/lt7182s.c index 28afc5f15ae8..aebd97af2741 100644 --- a/drivers/hwmon/pmbus/lt7182s.c +++ b/drivers/hwmon/pmbus/lt7182s.c @@ -168,7 +168,7 @@ static int lt7182s_probe(struct i2c_client *client) } static const struct i2c_device_id lt7182s_id[] = { - { "lt7182s", 0 }, + { "lt7182s" }, {} }; MODULE_DEVICE_TABLE(i2c, lt7182s_id); diff --git a/drivers/hwmon/pmbus/ltc3815.c b/drivers/hwmon/pmbus/ltc3815.c index f2023b17aa8d..f58a8cedb0d7 100644 --- a/drivers/hwmon/pmbus/ltc3815.c +++ b/drivers/hwmon/pmbus/ltc3815.c @@ -143,7 +143,7 @@ static int ltc3815_write_word_data(struct i2c_client *client, int page, } static const struct i2c_device_id ltc3815_id[] = { - {"ltc3815", 0}, + {"ltc3815"}, { } }; MODULE_DEVICE_TABLE(i2c, ltc3815_id); diff --git a/drivers/hwmon/pmbus/max15301.c b/drivers/hwmon/pmbus/max15301.c index 2cfaa62aedd6..c79cdf10bbec 100644 --- a/drivers/hwmon/pmbus/max15301.c +++ b/drivers/hwmon/pmbus/max15301.c @@ -23,7 +23,7 @@ #include "pmbus.h" static const struct i2c_device_id max15301_id[] = { - {"bmr461", 0}, + {"bmr461"}, {"max15301", 0}, {} }; diff --git a/drivers/hwmon/pmbus/max16064.c b/drivers/hwmon/pmbus/max16064.c index a573a0ab9e48..98e2b5dd5841 100644 --- a/drivers/hwmon/pmbus/max16064.c +++ b/drivers/hwmon/pmbus/max16064.c @@ -91,7 +91,7 @@ static int max16064_probe(struct i2c_client *client) } static const struct i2c_device_id max16064_id[] = { - {"max16064", 0}, + {"max16064"}, {} }; diff --git a/drivers/hwmon/pmbus/max20751.c b/drivers/hwmon/pmbus/max20751.c index 6ebd71cd081b..8f23c1eb559e 100644 --- a/drivers/hwmon/pmbus/max20751.c +++ b/drivers/hwmon/pmbus/max20751.c @@ -32,7 +32,7 @@ static int max20751_probe(struct i2c_client *client) } static const struct i2c_device_id max20751_id[] = { - {"max20751", 0}, + {"max20751"}, {} }; diff --git a/drivers/hwmon/pmbus/max31785.c b/drivers/hwmon/pmbus/max31785.c index 5d13bbfc8f47..09218dba8965 100644 --- a/drivers/hwmon/pmbus/max31785.c +++ b/drivers/hwmon/pmbus/max31785.c @@ -518,9 +518,9 @@ static int max31785_probe(struct i2c_client *client) } static const struct i2c_device_id max31785_id[] = { - { "max31785", 0 }, - { "max31785a", 0 }, - { "max31785b", 0 }, + { "max31785" }, + { "max31785a" }, + { "max31785b" }, { }, }; diff --git a/drivers/hwmon/pmbus/max8688.c b/drivers/hwmon/pmbus/max8688.c index ae8573fdf5ba..5d5b6aeefa80 100644 --- a/drivers/hwmon/pmbus/max8688.c +++ b/drivers/hwmon/pmbus/max8688.c @@ -171,7 +171,7 @@ static int max8688_probe(struct i2c_client *client) } static const struct i2c_device_id max8688_id[] = { - {"max8688", 0}, + {"max8688"}, { } }; diff --git a/drivers/hwmon/pmbus/mp2888.c b/drivers/hwmon/pmbus/mp2888.c index 50662ed8e3d5..3b45f126b611 100644 --- a/drivers/hwmon/pmbus/mp2888.c +++ b/drivers/hwmon/pmbus/mp2888.c @@ -378,7 +378,7 @@ static int mp2888_probe(struct i2c_client *client) } static const struct i2c_device_id mp2888_id[] = { - {"mp2888", 0}, + {"mp2888"}, {} }; diff --git a/drivers/hwmon/pmbus/mp5990.c b/drivers/hwmon/pmbus/mp5990.c index 1dfbab25a064..5d1d5eac89da 100644 --- a/drivers/hwmon/pmbus/mp5990.c +++ b/drivers/hwmon/pmbus/mp5990.c @@ -158,7 +158,7 @@ static const struct of_device_id mp5990_of_match[] = { }; static const struct i2c_device_id mp5990_id[] = { - {"mp5990", 0}, + {"mp5990"}, { } }; MODULE_DEVICE_TABLE(i2c, mp5990_id); diff --git a/drivers/hwmon/pmbus/mpq8785.c b/drivers/hwmon/pmbus/mpq8785.c index 4e2549cc8120..7f87e117b49d 100644 --- a/drivers/hwmon/pmbus/mpq8785.c +++ b/drivers/hwmon/pmbus/mpq8785.c @@ -62,7 +62,7 @@ static int mpq8785_probe(struct i2c_client *client) }; static const struct i2c_device_id mpq8785_id[] = { - { "mpq8785", 0 }, + { "mpq8785" }, { }, }; MODULE_DEVICE_TABLE(i2c, mpq8785_id); diff --git a/drivers/hwmon/pmbus/pli1209bc.c b/drivers/hwmon/pmbus/pli1209bc.c index c95433790b11..2c6c9ec2a652 100644 --- a/drivers/hwmon/pmbus/pli1209bc.c +++ b/drivers/hwmon/pmbus/pli1209bc.c @@ -141,7 +141,7 @@ static int pli1209bc_probe(struct i2c_client *client) } static const struct i2c_device_id pli1209bc_id[] = { - {"pli1209bc", 0}, + {"pli1209bc"}, {} }; diff --git a/drivers/hwmon/pmbus/pm6764tr.c b/drivers/hwmon/pmbus/pm6764tr.c index 2a16504c85b7..23f15b608dcf 100644 --- a/drivers/hwmon/pmbus/pm6764tr.c +++ b/drivers/hwmon/pmbus/pm6764tr.c @@ -48,7 +48,7 @@ static int pm6764tr_probe(struct i2c_client *client) } static const struct i2c_device_id pm6764tr_id[] = { - {"pm6764tr", 0}, + {"pm6764tr"}, {} }; MODULE_DEVICE_TABLE(i2c, pm6764tr_id); diff --git a/drivers/hwmon/pmbus/pxe1610.c b/drivers/hwmon/pmbus/pxe1610.c index e2790a682dc8..5ac476d3cdd2 100644 --- a/drivers/hwmon/pmbus/pxe1610.c +++ b/drivers/hwmon/pmbus/pxe1610.c @@ -127,9 +127,9 @@ static int pxe1610_probe(struct i2c_client *client) } static const struct i2c_device_id pxe1610_id[] = { - {"pxe1610", 0}, - {"pxe1110", 0}, - {"pxm1310", 0}, + {"pxe1610"}, + {"pxe1110"}, + {"pxm1310"}, {} }; diff --git a/drivers/hwmon/pmbus/stpddc60.c b/drivers/hwmon/pmbus/stpddc60.c index be9076dcc2db..34d0f06f4845 100644 --- a/drivers/hwmon/pmbus/stpddc60.c +++ b/drivers/hwmon/pmbus/stpddc60.c @@ -18,8 +18,8 @@ #define STPDDC60_MFR_UV_LIMIT_OFFSET 0xe6 static const struct i2c_device_id stpddc60_id[] = { - {"stpddc60", 0}, - {"bmr481", 0}, + {"stpddc60"}, + {"bmr481"}, {} }; MODULE_DEVICE_TABLE(i2c, stpddc60_id); diff --git a/drivers/hwmon/pmbus/tda38640.c b/drivers/hwmon/pmbus/tda38640.c index c31889a036f0..044d5fbdf9eb 100644 --- a/drivers/hwmon/pmbus/tda38640.c +++ b/drivers/hwmon/pmbus/tda38640.c @@ -195,7 +195,7 @@ static int tda38640_probe(struct i2c_client *client) } static const struct i2c_device_id tda38640_id[] = { - {"tda38640", 0}, + {"tda38640"}, {} }; MODULE_DEVICE_TABLE(i2c, tda38640_id); diff --git a/drivers/hwmon/pmbus/tps40422.c b/drivers/hwmon/pmbus/tps40422.c index ea0074a6b9fc..d99b9850ea36 100644 --- a/drivers/hwmon/pmbus/tps40422.c +++ b/drivers/hwmon/pmbus/tps40422.c @@ -31,7 +31,7 @@ static int tps40422_probe(struct i2c_client *client) } static const struct i2c_device_id tps40422_id[] = { - {"tps40422", 0}, + {"tps40422"}, {} }; diff --git a/drivers/hwmon/pmbus/tps546d24.c b/drivers/hwmon/pmbus/tps546d24.c index 69bbdb6c680b..520ca37269f7 100644 --- a/drivers/hwmon/pmbus/tps546d24.c +++ b/drivers/hwmon/pmbus/tps546d24.c @@ -42,7 +42,7 @@ static int tps546d24_probe(struct i2c_client *client) } static const struct i2c_device_id tps546d24_id[] = { - {"tps546d24", 0}, + {"tps546d24"}, {} }; MODULE_DEVICE_TABLE(i2c, tps546d24_id); diff --git a/drivers/hwmon/pmbus/xdp710.c b/drivers/hwmon/pmbus/xdp710.c index 03a5b937c221..dd107e83f612 100644 --- a/drivers/hwmon/pmbus/xdp710.c +++ b/drivers/hwmon/pmbus/xdp710.c @@ -110,7 +110,7 @@ static const struct of_device_id xdp710_of_match[] = { }; static const struct i2c_device_id xdp710_id[] = { - {"xdp710", 0}, + {"xdp710"}, { } }; MODULE_DEVICE_TABLE(i2c, xdp710_id); diff --git a/drivers/hwmon/pmbus/xdpe12284.c b/drivers/hwmon/pmbus/xdpe12284.c index 37d08dd427d5..facb1201aa43 100644 --- a/drivers/hwmon/pmbus/xdpe12284.c +++ b/drivers/hwmon/pmbus/xdpe12284.c @@ -164,9 +164,9 @@ static int xdpe122_probe(struct i2c_client *client) } static const struct i2c_device_id xdpe122_id[] = { - {"xdpe11280", 0}, - {"xdpe12254", 0}, - {"xdpe12284", 0}, + {"xdpe11280"}, + {"xdpe12254"}, + {"xdpe12284"}, {} }; diff --git a/drivers/hwmon/pmbus/xdpe152c4.c b/drivers/hwmon/pmbus/xdpe152c4.c index 235e6b41ae4c..7f3b31d4f033 100644 --- a/drivers/hwmon/pmbus/xdpe152c4.c +++ b/drivers/hwmon/pmbus/xdpe152c4.c @@ -44,8 +44,8 @@ static int xdpe152_probe(struct i2c_client *client) } static const struct i2c_device_id xdpe152_id[] = { - {"xdpe152c4", 0}, - {"xdpe15284", 0}, + {"xdpe152c4"}, + {"xdpe15284"}, {} }; diff --git a/drivers/hwmon/pt5161l.c b/drivers/hwmon/pt5161l.c index 60361e39c474..b0d58a26d499 100644 --- a/drivers/hwmon/pt5161l.c +++ b/drivers/hwmon/pt5161l.c @@ -630,7 +630,7 @@ static const struct acpi_device_id __maybe_unused pt5161l_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, pt5161l_acpi_match); static const struct i2c_device_id pt5161l_id[] = { - { "pt5161l", 0 }, + { "pt5161l" }, {} }; MODULE_DEVICE_TABLE(i2c, pt5161l_id); diff --git a/drivers/hwmon/sbrmi.c b/drivers/hwmon/sbrmi.c index 4318f5121145..d48d8e5460ff 100644 --- a/drivers/hwmon/sbrmi.c +++ b/drivers/hwmon/sbrmi.c @@ -328,7 +328,7 @@ static int sbrmi_probe(struct i2c_client *client) } static const struct i2c_device_id sbrmi_id[] = { - {"sbrmi", 0}, + {"sbrmi"}, {} }; MODULE_DEVICE_TABLE(i2c, sbrmi_id); diff --git a/drivers/hwmon/sbtsi_temp.c b/drivers/hwmon/sbtsi_temp.c index a4181acb1aa6..3c839f56c460 100644 --- a/drivers/hwmon/sbtsi_temp.c +++ b/drivers/hwmon/sbtsi_temp.c @@ -218,7 +218,7 @@ static int sbtsi_probe(struct i2c_client *client) } static const struct i2c_device_id sbtsi_id[] = { - {"sbtsi", 0}, + {"sbtsi"}, {} }; MODULE_DEVICE_TABLE(i2c, sbtsi_id); diff --git a/drivers/hwmon/sht21.c b/drivers/hwmon/sht21.c index 55c179475208..ad1b827ea782 100644 --- a/drivers/hwmon/sht21.c +++ b/drivers/hwmon/sht21.c @@ -278,7 +278,7 @@ static int sht21_probe(struct i2c_client *client) /* Device ID table */ static const struct i2c_device_id sht21_id[] = { - { "sht21", 0 }, + { "sht21" }, { } }; MODULE_DEVICE_TABLE(i2c, sht21_id); diff --git a/drivers/hwmon/sht4x.c b/drivers/hwmon/sht4x.c index 4883755d4b1e..b8916d2735b5 100644 --- a/drivers/hwmon/sht4x.c +++ b/drivers/hwmon/sht4x.c @@ -276,7 +276,7 @@ static int sht4x_probe(struct i2c_client *client) } static const struct i2c_device_id sht4x_id[] = { - { "sht4x", 0 }, + { "sht4x" }, { }, }; MODULE_DEVICE_TABLE(i2c, sht4x_id); diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c index d20800a1f02b..21103af4e139 100644 --- a/drivers/hwmon/smsc47m192.c +++ b/drivers/hwmon/smsc47m192.c @@ -618,7 +618,7 @@ static int smsc47m192_probe(struct i2c_client *client) } static const struct i2c_device_id smsc47m192_id[] = { - { "smsc47m192", 0 }, + { "smsc47m192" }, { } }; MODULE_DEVICE_TABLE(i2c, smsc47m192_id); diff --git a/drivers/hwmon/stts751.c b/drivers/hwmon/stts751.c index 847c99376930..427a65dd6f19 100644 --- a/drivers/hwmon/stts751.c +++ b/drivers/hwmon/stts751.c @@ -72,7 +72,7 @@ static const int stts751_intervals[] = { }; static const struct i2c_device_id stts751_id[] = { - { "stts751", 0 }, + { "stts751" }, { } }; diff --git a/drivers/hwmon/tc654.c b/drivers/hwmon/tc654.c index 42a9658f1bc2..39fe5836f237 100644 --- a/drivers/hwmon/tc654.c +++ b/drivers/hwmon/tc654.c @@ -550,8 +550,8 @@ static int tc654_probe(struct i2c_client *client) } static const struct i2c_device_id tc654_id[] = { - {"tc654", 0}, - {"tc655", 0}, + {"tc654"}, + {"tc655"}, {} }; diff --git a/drivers/hwmon/tc74.c b/drivers/hwmon/tc74.c index 03950670bd78..9984373a25fb 100644 --- a/drivers/hwmon/tc74.c +++ b/drivers/hwmon/tc74.c @@ -151,7 +151,7 @@ static int tc74_probe(struct i2c_client *client) } static const struct i2c_device_id tc74_id[] = { - { "tc74", 0 }, + { "tc74" }, {} }; MODULE_DEVICE_TABLE(i2c, tc74_id); diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c index 2506c78590af..8af44a33055f 100644 --- a/drivers/hwmon/tmp102.c +++ b/drivers/hwmon/tmp102.c @@ -286,7 +286,7 @@ static int tmp102_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(tmp102_dev_pm_ops, tmp102_suspend, tmp102_resume); static const struct i2c_device_id tmp102_id[] = { - { "tmp102", 0 }, + { "tmp102" }, { } }; MODULE_DEVICE_TABLE(i2c, tmp102_id); diff --git a/drivers/hwmon/tmp103.c b/drivers/hwmon/tmp103.c index a84c29a3a765..f271a03e05ae 100644 --- a/drivers/hwmon/tmp103.c +++ b/drivers/hwmon/tmp103.c @@ -197,7 +197,7 @@ static int tmp103_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(tmp103_dev_pm_ops, tmp103_suspend, tmp103_resume); static const struct i2c_device_id tmp103_id[] = { - { "tmp103", 0 }, + { "tmp103" }, { } }; MODULE_DEVICE_TABLE(i2c, tmp103_id); diff --git a/drivers/hwmon/tmp108.c b/drivers/hwmon/tmp108.c index d7a09ab2bc11..a82bbc959eb1 100644 --- a/drivers/hwmon/tmp108.c +++ b/drivers/hwmon/tmp108.c @@ -413,7 +413,7 @@ static int tmp108_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(tmp108_dev_pm_ops, tmp108_suspend, tmp108_resume); static const struct i2c_device_id tmp108_i2c_ids[] = { - { "tmp108", 0 }, + { "tmp108" }, { } }; MODULE_DEVICE_TABLE(i2c, tmp108_i2c_ids); diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c index 9681eaa06c8e..ace854b370a0 100644 --- a/drivers/hwmon/w83791d.c +++ b/drivers/hwmon/w83791d.c @@ -328,7 +328,7 @@ static void w83791d_print_debug(struct w83791d_data *data, struct device *dev); static void w83791d_init_client(struct i2c_client *client); static const struct i2c_device_id w83791d_id[] = { - { "w83791d", 0 }, + { "w83791d" }, { } }; MODULE_DEVICE_TABLE(i2c, w83791d_id); diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index 69ce379a9e13..b0b5f60eea53 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c @@ -296,7 +296,7 @@ static void w83792d_print_debug(struct w83792d_data *data, struct device *dev); static void w83792d_init_client(struct i2c_client *client); static const struct i2c_device_id w83792d_id[] = { - { "w83792d", 0 }, + { "w83792d" }, { } }; MODULE_DEVICE_TABLE(i2c, w83792d_id); diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c index 96bab94ba899..0acf6bd0227f 100644 --- a/drivers/hwmon/w83793.c +++ b/drivers/hwmon/w83793.c @@ -291,7 +291,7 @@ static void w83793_update_nonvolatile(struct device *dev); static struct w83793_data *w83793_update_device(struct device *dev); static const struct i2c_device_id w83793_id[] = { - { "w83793", 0 }, + { "w83793" }, { } }; MODULE_DEVICE_TABLE(i2c, w83793_id); diff --git a/drivers/hwmon/w83l785ts.c b/drivers/hwmon/w83l785ts.c index 9c11ed69c055..df77b53a1b2f 100644 --- a/drivers/hwmon/w83l785ts.c +++ b/drivers/hwmon/w83l785ts.c @@ -74,7 +74,7 @@ static struct w83l785ts_data *w83l785ts_update_device(struct device *dev); */ static const struct i2c_device_id w83l785ts_id[] = { - { "w83l785ts", 0 }, + { "w83l785ts" }, { } }; MODULE_DEVICE_TABLE(i2c, w83l785ts_id); diff --git a/drivers/hwmon/w83l786ng.c b/drivers/hwmon/w83l786ng.c index 75874cf7851c..9b81bd406e05 100644 --- a/drivers/hwmon/w83l786ng.c +++ b/drivers/hwmon/w83l786ng.c @@ -741,7 +741,7 @@ w83l786ng_probe(struct i2c_client *client) } static const struct i2c_device_id w83l786ng_id[] = { - { "w83l786ng", 0 }, + { "w83l786ng" }, { } }; MODULE_DEVICE_TABLE(i2c, w83l786ng_id); -- cgit v1.2.3 From b2728c095c0aeefaa7a0f6955fb76dd50f9906e4 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Tue, 30 Apr 2024 23:09:07 +0200 Subject: hwmon: (stts751) Remove an unused field in struct stts751_priv In "struct stts751_priv", the 'smbus_timeout' field is unused. Remove it. Found with cppcheck, unusedStructMember. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/94ccf9caaa6b0101351bf381f09f4428c5e0835c.1714511322.git.christophe.jaillet@wanadoo.fr Signed-off-by: Guenter Roeck --- drivers/hwmon/stts751.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/stts751.c b/drivers/hwmon/stts751.c index 427a65dd6f19..e7632081a1d1 100644 --- a/drivers/hwmon/stts751.c +++ b/drivers/hwmon/stts751.c @@ -91,7 +91,6 @@ struct stts751_priv { int event_max, event_min; int therm; int hyst; - bool smbus_timeout; int temp; unsigned long last_update, last_alert_update; u8 config; -- cgit v1.2.3 From cfdafddf161dcafad0bfdf9b4515e19a9bd6f791 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Tue, 30 Apr 2024 21:35:37 +0200 Subject: hwmon: (npcm750-pwm-fan) Remove an unused field in struct npcm7xx_cooling_device In "struct npcm7xx_cooling_device", the 'fan_clk_freq' field is unused. Remove it. Found with cppcheck, unusedStructMember. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/74eee8aa739f94b8c6425ce3e37a427ca92243ea.1714505655.git.christophe.jaillet@wanadoo.fr Signed-off-by: Guenter Roeck --- drivers/hwmon/npcm750-pwm-fan.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/npcm750-pwm-fan.c b/drivers/hwmon/npcm750-pwm-fan.c index 904816abb7c4..6d92a3b89198 100644 --- a/drivers/hwmon/npcm750-pwm-fan.c +++ b/drivers/hwmon/npcm750-pwm-fan.c @@ -197,7 +197,6 @@ struct npcm7xx_pwm_fan_data { void __iomem *fan_base; int pwm_modules; unsigned long pwm_clk_freq; - unsigned long fan_clk_freq; struct clk *pwm_clk; struct clk *fan_clk; struct mutex pwm_lock[NPCM7XX_PWM_MAX_MODULES]; -- cgit v1.2.3 From 1d4d6733594d407e54153b8e031ba6356ceba81e Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Tue, 30 Apr 2024 21:35:38 +0200 Subject: hwmon: (npcm750-pwm-fan) Remove another unused field in struct npcm7xx_cooling_device In "struct npcm7xx_cooling_device", the 'pwm_clk_freq' field is only written and never used. Remove it and update npcm7xx_pwm_init() accordingly. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/2ff738663d40ac5ae3d0b4d2e688ff7e36032be8.1714505655.git.christophe.jaillet@wanadoo.fr Signed-off-by: Guenter Roeck --- drivers/hwmon/npcm750-pwm-fan.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/npcm750-pwm-fan.c b/drivers/hwmon/npcm750-pwm-fan.c index 6d92a3b89198..bc8db1dc595d 100644 --- a/drivers/hwmon/npcm750-pwm-fan.c +++ b/drivers/hwmon/npcm750-pwm-fan.c @@ -196,7 +196,6 @@ struct npcm7xx_pwm_fan_data { void __iomem *pwm_base; void __iomem *fan_base; int pwm_modules; - unsigned long pwm_clk_freq; struct clk *pwm_clk; struct clk *fan_clk; struct mutex pwm_lock[NPCM7XX_PWM_MAX_MODULES]; @@ -691,11 +690,12 @@ static u32 npcm7xx_pwm_init(struct npcm7xx_pwm_fan_data *data) { int m, ch; u32 prescale_val, output_freq; + unsigned long pwm_clk_freq; - data->pwm_clk_freq = clk_get_rate(data->pwm_clk); + pwm_clk_freq = clk_get_rate(data->pwm_clk); /* Adjust NPCM7xx PWMs output frequency to ~25Khz */ - output_freq = data->pwm_clk_freq / PWN_CNT_DEFAULT; + output_freq = pwm_clk_freq / PWN_CNT_DEFAULT; prescale_val = DIV_ROUND_CLOSEST(output_freq, PWM_OUTPUT_FREQ_25KHZ); /* If prescale_val = 0, then the prescale output clock is stopped */ -- cgit v1.2.3 From cffb8d74bd4e9dd0653c7093c4a5164a72c52b1f Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 29 Apr 2024 18:40:10 -0500 Subject: hwmon: (adc128d818) Use devm_regulator_get_enable_read_voltage() We can reduce boilerplate code and eliminate the driver remove() function by using devm_regulator_get_enable_read_voltage(). A new external_vref flag is added since we no longer have the handle to the regulator to check if it is present. Reviewed-by: Jonathan Cameron Signed-off-by: David Lechner Acked-by: Guenter Roeck Link: https://lore.kernel.org/r/20240429-regulator-get-enable-get-votlage-v2-2-b1f11ab766c1@baylibre.com Signed-off-by: Mark Brown --- drivers/hwmon/adc128d818.c | 57 ++++++++++++++-------------------------------- 1 file changed, 17 insertions(+), 40 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/adc128d818.c b/drivers/hwmon/adc128d818.c index 46e3c8c50765..2a35acb011eb 100644 --- a/drivers/hwmon/adc128d818.c +++ b/drivers/hwmon/adc128d818.c @@ -58,7 +58,6 @@ static const u8 num_inputs[] = { 7, 8, 4, 6 }; struct adc128_data { struct i2c_client *client; - struct regulator *regulator; int vref; /* Reference voltage in mV */ struct mutex update_lock; u8 mode; /* Operation mode */ @@ -389,7 +388,7 @@ static int adc128_detect(struct i2c_client *client, struct i2c_board_info *info) return 0; } -static int adc128_init_client(struct adc128_data *data) +static int adc128_init_client(struct adc128_data *data, bool external_vref) { struct i2c_client *client = data->client; int err; @@ -408,7 +407,7 @@ static int adc128_init_client(struct adc128_data *data) regval |= data->mode << 1; /* If external vref is selected, configure the chip to use it */ - if (data->regulator) + if (external_vref) regval |= 0x01; /* Write advanced configuration register */ @@ -430,9 +429,9 @@ static int adc128_init_client(struct adc128_data *data) static int adc128_probe(struct i2c_client *client) { struct device *dev = &client->dev; - struct regulator *regulator; struct device *hwmon_dev; struct adc128_data *data; + bool external_vref; int err, vref; data = devm_kzalloc(dev, sizeof(struct adc128_data), GFP_KERNEL); @@ -440,20 +439,15 @@ static int adc128_probe(struct i2c_client *client) return -ENOMEM; /* vref is optional. If specified, is used as chip reference voltage */ - regulator = devm_regulator_get_optional(dev, "vref"); - if (!IS_ERR(regulator)) { - data->regulator = regulator; - err = regulator_enable(regulator); - if (err < 0) - return err; - vref = regulator_get_voltage(regulator); - if (vref < 0) { - err = vref; - goto error; - } - data->vref = DIV_ROUND_CLOSEST(vref, 1000); - } else { + vref = devm_regulator_get_enable_read_voltage(dev, "vref"); + if (vref == -ENODEV) { + external_vref = false; data->vref = 2560; /* 2.56V, in mV */ + } else if (vref < 0) { + return vref; + } else { + external_vref = true; + data->vref = DIV_ROUND_CLOSEST(vref, 1000); } /* Operation mode is optional. If unspecified, keep current mode */ @@ -461,13 +455,12 @@ static int adc128_probe(struct i2c_client *client) if (data->mode > 3) { dev_err(dev, "invalid operation mode %d\n", data->mode); - err = -EINVAL; - goto error; + return -EINVAL; } } else { err = i2c_smbus_read_byte_data(client, ADC128_REG_CONFIG_ADV); if (err < 0) - goto error; + return err; data->mode = (err >> 1) & ADC128_REG_MASK; } @@ -476,31 +469,16 @@ static int adc128_probe(struct i2c_client *client) mutex_init(&data->update_lock); /* Initialize the chip */ - err = adc128_init_client(data); + err = adc128_init_client(data, external_vref); if (err < 0) - goto error; + return err; hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, data, adc128_groups); - if (IS_ERR(hwmon_dev)) { - err = PTR_ERR(hwmon_dev); - goto error; - } + if (IS_ERR(hwmon_dev)) + return PTR_ERR(hwmon_dev); return 0; - -error: - if (data->regulator) - regulator_disable(data->regulator); - return err; -} - -static void adc128_remove(struct i2c_client *client) -{ - struct adc128_data *data = i2c_get_clientdata(client); - - if (data->regulator) - regulator_disable(data->regulator); } static const struct i2c_device_id adc128_id[] = { @@ -522,7 +500,6 @@ static struct i2c_driver adc128_driver = { .of_match_table = of_match_ptr(adc128_of_match), }, .probe = adc128_probe, - .remove = adc128_remove, .id_table = adc128_id, .detect = adc128_detect, .address_list = normal_i2c, -- cgit v1.2.3 From d72fd5228c9f2136a3143daf5c7822140211883a Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 29 Apr 2024 18:40:11 -0500 Subject: hwmon: (da9052) Use devm_regulator_get_enable_read_voltage() We can reduce boilerplate code by using devm_regulator_get_enable_read_voltage(). Reviewed-by: Jonathan Cameron Signed-off-by: David Lechner Acked-by: Guenter Roeck Link: https://lore.kernel.org/r/20240429-regulator-get-enable-get-votlage-v2-3-b1f11ab766c1@baylibre.com Signed-off-by: Mark Brown --- drivers/hwmon/da9052-hwmon.c | 38 ++++++++++---------------------------- 1 file changed, 10 insertions(+), 28 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/da9052-hwmon.c b/drivers/hwmon/da9052-hwmon.c index 2bd7ae8100d7..7fb0c57dfef5 100644 --- a/drivers/hwmon/da9052-hwmon.c +++ b/drivers/hwmon/da9052-hwmon.c @@ -26,7 +26,6 @@ struct da9052_hwmon { struct mutex hwmon_lock; bool tsi_as_adc; int tsiref_mv; - struct regulator *tsiref; struct completion tsidone; }; @@ -397,7 +396,7 @@ static int da9052_hwmon_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct da9052_hwmon *hwmon; struct device *hwmon_dev; - int err; + int err, tsiref_uv; hwmon = devm_kzalloc(dev, sizeof(struct da9052_hwmon), GFP_KERNEL); if (!hwmon) @@ -414,32 +413,20 @@ static int da9052_hwmon_probe(struct platform_device *pdev) device_property_read_bool(pdev->dev.parent, "dlg,tsi-as-adc"); if (hwmon->tsi_as_adc) { - hwmon->tsiref = devm_regulator_get(pdev->dev.parent, "tsiref"); - if (IS_ERR(hwmon->tsiref)) { - err = PTR_ERR(hwmon->tsiref); - dev_err(&pdev->dev, "failed to get tsiref: %d", err); - return err; - } - - err = regulator_enable(hwmon->tsiref); - if (err) - return err; - - hwmon->tsiref_mv = regulator_get_voltage(hwmon->tsiref); - if (hwmon->tsiref_mv < 0) { - err = hwmon->tsiref_mv; - goto exit_regulator; - } + tsiref_uv = devm_regulator_get_enable_read_voltage(dev->parent, + "tsiref"); + if (tsiref_uv < 0) + return dev_err_probe(dev, tsiref_uv, + "failed to get tsiref voltage\n"); /* convert from microvolt (DT) to millivolt (hwmon) */ - hwmon->tsiref_mv /= 1000; + hwmon->tsiref_mv = tsiref_uv / 1000; /* TSIREF limits from datasheet */ if (hwmon->tsiref_mv < 1800 || hwmon->tsiref_mv > 2600) { dev_err(hwmon->da9052->dev, "invalid TSIREF voltage: %d", hwmon->tsiref_mv); - err = -ENXIO; - goto exit_regulator; + return -ENXIO; } /* disable touchscreen features */ @@ -456,7 +443,7 @@ static int da9052_hwmon_probe(struct platform_device *pdev) if (err) { dev_err(&pdev->dev, "Failed to register TSIRDY IRQ: %d", err); - goto exit_regulator; + return err; } } @@ -472,9 +459,6 @@ static int da9052_hwmon_probe(struct platform_device *pdev) exit_irq: if (hwmon->tsi_as_adc) da9052_free_irq(hwmon->da9052, DA9052_IRQ_TSIREADY, hwmon); -exit_regulator: - if (hwmon->tsiref) - regulator_disable(hwmon->tsiref); return err; } @@ -483,10 +467,8 @@ static void da9052_hwmon_remove(struct platform_device *pdev) { struct da9052_hwmon *hwmon = platform_get_drvdata(pdev); - if (hwmon->tsi_as_adc) { + if (hwmon->tsi_as_adc) da9052_free_irq(hwmon->da9052, DA9052_IRQ_TSIREADY, hwmon); - regulator_disable(hwmon->tsiref); - } } static struct platform_driver da9052_hwmon_driver = { -- cgit v1.2.3 From 45bf8305fb2ef684e53fd0dcf1cc7e7b456f3478 Mon Sep 17 00:00:00 2001 From: Naresh Solanki Date: Fri, 3 May 2024 17:30:19 +0530 Subject: hwmon: (max6639) Use regmap Add regmap support & remove local caching. Signed-off-by: Naresh Solanki Link: https://lore.kernel.org/r/20240503120020.3450972-1-naresh.solanki@9elements.com Signed-off-by: Guenter Roeck --- drivers/hwmon/Kconfig | 1 + drivers/hwmon/max6639.c | 339 +++++++++++++++++++++--------------------------- 2 files changed, 150 insertions(+), 190 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index bafc0058c728..e14ae18a973b 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -1233,6 +1233,7 @@ config SENSORS_MAX6621 config SENSORS_MAX6639 tristate "Maxim MAX6639 sensor chip" depends on I2C + select REGMAP_I2C help If you say yes here you get support for the MAX6639 sensor chips. diff --git a/drivers/hwmon/max6639.c b/drivers/hwmon/max6639.c index 5dd0349e8bd0..cbb595fe47aa 100644 --- a/drivers/hwmon/max6639.c +++ b/drivers/hwmon/max6639.c @@ -20,6 +20,7 @@ #include #include #include +#include /* Addresses to scan */ static const unsigned short normal_i2c[] = { 0x2c, 0x2e, 0x2f, I2C_CLIENT_END }; @@ -57,6 +58,8 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2e, 0x2f, I2C_CLIENT_END }; #define MAX6639_FAN_CONFIG3_THERM_FULL_SPEED 0x40 +#define MAX6639_NUM_CHANNELS 2 + static const int rpm_ranges[] = { 2000, 4000, 8000, 16000 }; #define FAN_FROM_REG(val, rpm_range) ((val) == 0 || (val) == 255 ? \ @@ -67,22 +70,7 @@ static const int rpm_ranges[] = { 2000, 4000, 8000, 16000 }; * Client data (each client gets its own) */ struct max6639_data { - struct i2c_client *client; - struct mutex update_lock; - bool valid; /* true if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - - /* Register values sampled regularly */ - u16 temp[2]; /* Temperature, in 1/8 C, 0..255 C */ - bool temp_fault[2]; /* Detected temperature diode failure */ - u8 fan[2]; /* Register value: TACH count for fans >=30 */ - u8 status; /* Detected channel alarms and fan failures */ - - /* Register values only written to */ - u8 pwm[2]; /* Register value: Duty cycle 0..120 */ - u8 temp_therm[2]; /* THERM Temperature, 0..255 C (->_max) */ - u8 temp_alert[2]; /* ALERT Temperature, 0..255 C (->_crit) */ - u8 temp_ot[2]; /* OT Temperature, 0..255 C (->_emergency) */ + struct regmap *regmap; /* Register values initialized only once */ u8 ppr; /* Pulses per rotation 0..3 for 1..4 ppr */ @@ -92,90 +80,47 @@ struct max6639_data { struct regulator *reg; }; -static struct max6639_data *max6639_update_device(struct device *dev) -{ - struct max6639_data *data = dev_get_drvdata(dev); - struct i2c_client *client = data->client; - struct max6639_data *ret = data; - int i; - int status_reg; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { - int res; - - dev_dbg(&client->dev, "Starting max6639 update\n"); - - status_reg = i2c_smbus_read_byte_data(client, - MAX6639_REG_STATUS); - if (status_reg < 0) { - ret = ERR_PTR(status_reg); - goto abort; - } - - data->status = status_reg; - - for (i = 0; i < 2; i++) { - res = i2c_smbus_read_byte_data(client, - MAX6639_REG_FAN_CNT(i)); - if (res < 0) { - ret = ERR_PTR(res); - goto abort; - } - data->fan[i] = res; - - res = i2c_smbus_read_byte_data(client, - MAX6639_REG_TEMP_EXT(i)); - if (res < 0) { - ret = ERR_PTR(res); - goto abort; - } - data->temp[i] = res >> 5; - data->temp_fault[i] = res & 0x01; - - res = i2c_smbus_read_byte_data(client, - MAX6639_REG_TEMP(i)); - if (res < 0) { - ret = ERR_PTR(res); - goto abort; - } - data->temp[i] |= res << 3; - } - - data->last_updated = jiffies; - data->valid = true; - } -abort: - mutex_unlock(&data->update_lock); - - return ret; -} - static ssize_t temp_input_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { long temp; - struct max6639_data *data = max6639_update_device(dev); + struct max6639_data *data = dev_get_drvdata(dev); struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + unsigned int val; + int res; + + /* + * Lock isn't needed as MAX6639_REG_TEMP wpnt change for at least 250ms after reading + * MAX6639_REG_TEMP_EXT + */ + res = regmap_read(data->regmap, MAX6639_REG_TEMP_EXT(attr->index), &val); + if (res < 0) + return res; + + temp = val >> 5; + res = regmap_read(data->regmap, MAX6639_REG_TEMP(attr->index), &val); + if (res < 0) + return res; - if (IS_ERR(data)) - return PTR_ERR(data); + temp |= val << 3; + temp *= 125; - temp = data->temp[attr->index] * 125; return sprintf(buf, "%ld\n", temp); } static ssize_t temp_fault_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { - struct max6639_data *data = max6639_update_device(dev); + struct max6639_data *data = dev_get_drvdata(dev); struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + unsigned int val; + int res; - if (IS_ERR(data)) - return PTR_ERR(data); + res = regmap_read(data->regmap, MAX6639_REG_TEMP_EXT(attr->index), &val); + if (res < 0) + return res; - return sprintf(buf, "%d\n", data->temp_fault[attr->index]); + return sprintf(buf, "%d\n", val & 1); } static ssize_t temp_max_show(struct device *dev, @@ -183,8 +128,14 @@ static ssize_t temp_max_show(struct device *dev, { struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); struct max6639_data *data = dev_get_drvdata(dev); + unsigned int val; + int res; - return sprintf(buf, "%d\n", (data->temp_therm[attr->index] * 1000)); + res = regmap_read(data->regmap, MAX6639_REG_THERM_LIMIT(attr->index), &val); + if (res < 0) + return res; + + return sprintf(buf, "%d\n", (val * 1000)); } static ssize_t temp_max_store(struct device *dev, @@ -193,7 +144,6 @@ static ssize_t temp_max_store(struct device *dev, { struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); struct max6639_data *data = dev_get_drvdata(dev); - struct i2c_client *client = data->client; unsigned long val; int res; @@ -201,12 +151,8 @@ static ssize_t temp_max_store(struct device *dev, if (res) return res; - mutex_lock(&data->update_lock); - data->temp_therm[attr->index] = TEMP_LIMIT_TO_REG(val); - i2c_smbus_write_byte_data(client, - MAX6639_REG_THERM_LIMIT(attr->index), - data->temp_therm[attr->index]); - mutex_unlock(&data->update_lock); + regmap_write(data->regmap, MAX6639_REG_THERM_LIMIT(attr->index), + TEMP_LIMIT_TO_REG(val)); return count; } @@ -215,8 +161,14 @@ static ssize_t temp_crit_show(struct device *dev, { struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); struct max6639_data *data = dev_get_drvdata(dev); + unsigned int val; + int res; + + res = regmap_read(data->regmap, MAX6639_REG_ALERT_LIMIT(attr->index), &val); + if (res < 0) + return res; - return sprintf(buf, "%d\n", (data->temp_alert[attr->index] * 1000)); + return sprintf(buf, "%d\n", (val * 1000)); } static ssize_t temp_crit_store(struct device *dev, @@ -225,7 +177,6 @@ static ssize_t temp_crit_store(struct device *dev, { struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); struct max6639_data *data = dev_get_drvdata(dev); - struct i2c_client *client = data->client; unsigned long val; int res; @@ -233,12 +184,8 @@ static ssize_t temp_crit_store(struct device *dev, if (res) return res; - mutex_lock(&data->update_lock); - data->temp_alert[attr->index] = TEMP_LIMIT_TO_REG(val); - i2c_smbus_write_byte_data(client, - MAX6639_REG_ALERT_LIMIT(attr->index), - data->temp_alert[attr->index]); - mutex_unlock(&data->update_lock); + regmap_write(data->regmap, MAX6639_REG_ALERT_LIMIT(attr->index), + TEMP_LIMIT_TO_REG(val)); return count; } @@ -248,8 +195,14 @@ static ssize_t temp_emergency_show(struct device *dev, { struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); struct max6639_data *data = dev_get_drvdata(dev); + unsigned int val; + int res; + + res = regmap_read(data->regmap, MAX6639_REG_OT_LIMIT(attr->index), &val); + if (res < 0) + return res; - return sprintf(buf, "%d\n", (data->temp_ot[attr->index] * 1000)); + return sprintf(buf, "%d\n", (val * 1000)); } static ssize_t temp_emergency_store(struct device *dev, @@ -258,7 +211,6 @@ static ssize_t temp_emergency_store(struct device *dev, { struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); struct max6639_data *data = dev_get_drvdata(dev); - struct i2c_client *client = data->client; unsigned long val; int res; @@ -266,12 +218,8 @@ static ssize_t temp_emergency_store(struct device *dev, if (res) return res; - mutex_lock(&data->update_lock); - data->temp_ot[attr->index] = TEMP_LIMIT_TO_REG(val); - i2c_smbus_write_byte_data(client, - MAX6639_REG_OT_LIMIT(attr->index), - data->temp_ot[attr->index]); - mutex_unlock(&data->update_lock); + regmap_write(data->regmap, MAX6639_REG_OT_LIMIT(attr->index), TEMP_LIMIT_TO_REG(val)); + return count; } @@ -280,8 +228,14 @@ static ssize_t pwm_show(struct device *dev, struct device_attribute *dev_attr, { struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); struct max6639_data *data = dev_get_drvdata(dev); + unsigned int val; + int res; - return sprintf(buf, "%d\n", data->pwm[attr->index] * 255 / 120); + res = regmap_read(data->regmap, MAX6639_REG_TARGTDUTY(attr->index), &val); + if (res < 0) + return res; + + return sprintf(buf, "%d\n", val * 255 / 120); } static ssize_t pwm_store(struct device *dev, @@ -290,7 +244,6 @@ static ssize_t pwm_store(struct device *dev, { struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); struct max6639_data *data = dev_get_drvdata(dev); - struct i2c_client *client = data->client; unsigned long val; int res; @@ -300,38 +253,39 @@ static ssize_t pwm_store(struct device *dev, val = clamp_val(val, 0, 255); - mutex_lock(&data->update_lock); - data->pwm[attr->index] = (u8)(val * 120 / 255); - i2c_smbus_write_byte_data(client, - MAX6639_REG_TARGTDUTY(attr->index), - data->pwm[attr->index]); - mutex_unlock(&data->update_lock); + regmap_write(data->regmap, MAX6639_REG_TARGTDUTY(attr->index), val * 120 / 255); + return count; } static ssize_t fan_input_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { - struct max6639_data *data = max6639_update_device(dev); + struct max6639_data *data = dev_get_drvdata(dev); struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + unsigned int val; + int res; - if (IS_ERR(data)) - return PTR_ERR(data); + res = regmap_read(data->regmap, MAX6639_REG_FAN_CNT(attr->index), &val); + if (res < 0) + return res; - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[attr->index], - data->rpm_range)); + return sprintf(buf, "%d\n", FAN_FROM_REG(val, data->rpm_range)); } static ssize_t alarm_show(struct device *dev, struct device_attribute *dev_attr, char *buf) { - struct max6639_data *data = max6639_update_device(dev); + struct max6639_data *data = dev_get_drvdata(dev); struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + unsigned int val; + int res; - if (IS_ERR(data)) - return PTR_ERR(data); + res = regmap_read(data->regmap, MAX6639_REG_STATUS, &val); + if (res < 0) + return res; - return sprintf(buf, "%d\n", !!(data->status & (1 << attr->index))); + return sprintf(buf, "%d\n", !!(val & (1 << attr->index))); } static SENSOR_DEVICE_ATTR_RO(temp1_input, temp_input, 0); @@ -401,6 +355,11 @@ static int rpm_range_to_reg(int range) return 1; /* default: 4000 RPM */ } +static int max6639_set_ppr(struct max6639_data *data, u8 channel, u8 ppr) +{ + return regmap_write(data->regmap, MAX6639_REG_FAN_PPR(channel), ppr << 6); +} + static int max6639_init_client(struct i2c_client *client, struct max6639_data *data) { @@ -408,94 +367,76 @@ static int max6639_init_client(struct i2c_client *client, dev_get_platdata(&client->dev); int i; int rpm_range = 1; /* default: 4000 RPM */ - int err; + int err, ppr; /* Reset chip to default values, see below for GCONFIG setup */ - err = i2c_smbus_write_byte_data(client, MAX6639_REG_GCONFIG, - MAX6639_GCONFIG_POR); + err = regmap_write(data->regmap, MAX6639_REG_GCONFIG, MAX6639_GCONFIG_POR); if (err) - goto exit; + return err; /* Fans pulse per revolution is 2 by default */ if (max6639_info && max6639_info->ppr > 0 && max6639_info->ppr < 5) - data->ppr = max6639_info->ppr; + ppr = max6639_info->ppr; else - data->ppr = 2; - data->ppr -= 1; + ppr = 2; + ppr -= 1; if (max6639_info) rpm_range = rpm_range_to_reg(max6639_info->rpm_range); data->rpm_range = rpm_range; - for (i = 0; i < 2; i++) { + for (i = 0; i < MAX6639_NUM_CHANNELS; i++) { /* Set Fan pulse per revolution */ - err = i2c_smbus_write_byte_data(client, - MAX6639_REG_FAN_PPR(i), - data->ppr << 6); + err = max6639_set_ppr(data, i, ppr); if (err) - goto exit; + return err; /* Fans config PWM, RPM */ - err = i2c_smbus_write_byte_data(client, - MAX6639_REG_FAN_CONFIG1(i), - MAX6639_FAN_CONFIG1_PWM | rpm_range); + err = regmap_write(data->regmap, MAX6639_REG_FAN_CONFIG1(i), + MAX6639_FAN_CONFIG1_PWM | rpm_range); if (err) - goto exit; + return err; /* Fans PWM polarity high by default */ if (max6639_info && max6639_info->pwm_polarity == 0) - err = i2c_smbus_write_byte_data(client, - MAX6639_REG_FAN_CONFIG2a(i), 0x00); + err = regmap_write(data->regmap, MAX6639_REG_FAN_CONFIG2a(i), 0x00); else - err = i2c_smbus_write_byte_data(client, - MAX6639_REG_FAN_CONFIG2a(i), 0x02); + err = regmap_write(data->regmap, MAX6639_REG_FAN_CONFIG2a(i), 0x02); if (err) - goto exit; + return err; /* * /THERM full speed enable, * PWM frequency 25kHz, see also GCONFIG below */ - err = i2c_smbus_write_byte_data(client, - MAX6639_REG_FAN_CONFIG3(i), - MAX6639_FAN_CONFIG3_THERM_FULL_SPEED | 0x03); + err = regmap_write(data->regmap, MAX6639_REG_FAN_CONFIG3(i), + MAX6639_FAN_CONFIG3_THERM_FULL_SPEED | 0x03); if (err) - goto exit; + return err; /* Max. temp. 80C/90C/100C */ - data->temp_therm[i] = 80; - data->temp_alert[i] = 90; - data->temp_ot[i] = 100; - err = i2c_smbus_write_byte_data(client, - MAX6639_REG_THERM_LIMIT(i), - data->temp_therm[i]); + err = regmap_write(data->regmap, MAX6639_REG_THERM_LIMIT(i), 80); if (err) - goto exit; - err = i2c_smbus_write_byte_data(client, - MAX6639_REG_ALERT_LIMIT(i), - data->temp_alert[i]); + return err; + err = regmap_write(data->regmap, MAX6639_REG_ALERT_LIMIT(i), 90); if (err) - goto exit; - err = i2c_smbus_write_byte_data(client, - MAX6639_REG_OT_LIMIT(i), data->temp_ot[i]); + return err; + err = regmap_write(data->regmap, MAX6639_REG_OT_LIMIT(i), 100); if (err) - goto exit; + return err; /* PWM 120/120 (i.e. 100%) */ - data->pwm[i] = 120; - err = i2c_smbus_write_byte_data(client, - MAX6639_REG_TARGTDUTY(i), data->pwm[i]); + err = regmap_write(data->regmap, MAX6639_REG_TARGTDUTY(i), 120); if (err) - goto exit; + return err; } /* Start monitoring */ - err = i2c_smbus_write_byte_data(client, MAX6639_REG_GCONFIG, - MAX6639_GCONFIG_DISABLE_TIMEOUT | MAX6639_GCONFIG_CH2_LOCAL | - MAX6639_GCONFIG_PWM_FREQ_HI); -exit: - return err; + return regmap_write(data->regmap, MAX6639_REG_GCONFIG, + MAX6639_GCONFIG_DISABLE_TIMEOUT | MAX6639_GCONFIG_CH2_LOCAL | + MAX6639_GCONFIG_PWM_FREQ_HI); + } /* Return 0 if detection is successful, -ENODEV otherwise */ @@ -524,6 +465,32 @@ static void max6639_regulator_disable(void *data) regulator_disable(data); } +static bool max6639_regmap_is_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX6639_REG_TEMP(0): + case MAX6639_REG_TEMP_EXT(0): + case MAX6639_REG_TEMP(1): + case MAX6639_REG_TEMP_EXT(1): + case MAX6639_REG_STATUS: + case MAX6639_REG_FAN_CNT(0): + case MAX6639_REG_FAN_CNT(1): + case MAX6639_REG_TARGTDUTY(0): + case MAX6639_REG_TARGTDUTY(1): + return true; + default: + return false; + } +} + +static const struct regmap_config max6639_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = MAX6639_REG_DEVREV, + .cache_type = REGCACHE_MAPLE, + .volatile_reg = max6639_regmap_is_volatile, +}; + static int max6639_probe(struct i2c_client *client) { struct device *dev = &client->dev; @@ -535,7 +502,11 @@ static int max6639_probe(struct i2c_client *client) if (!data) return -ENOMEM; - data->client = client; + data->regmap = devm_regmap_init_i2c(client, &max6639_regmap_config); + if (IS_ERR(data->regmap)) + return dev_err_probe(dev, + PTR_ERR(data->regmap), + "regmap initialization failed\n"); data->reg = devm_regulator_get_optional(dev, "fan"); if (IS_ERR(data->reg)) { @@ -558,8 +529,6 @@ static int max6639_probe(struct i2c_client *client) } } - mutex_init(&data->update_lock); - /* Initialize the max6639 chip */ err = max6639_init_client(client, data); if (err < 0) @@ -573,23 +542,17 @@ static int max6639_probe(struct i2c_client *client) static int max6639_suspend(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); struct max6639_data *data = dev_get_drvdata(dev); - int ret = i2c_smbus_read_byte_data(client, MAX6639_REG_GCONFIG); - - if (ret < 0) - return ret; if (data->reg) regulator_disable(data->reg); - return i2c_smbus_write_byte_data(client, - MAX6639_REG_GCONFIG, ret | MAX6639_GCONFIG_STANDBY); + return regmap_write_bits(data->regmap, MAX6639_REG_GCONFIG, MAX6639_GCONFIG_STANDBY, + MAX6639_GCONFIG_STANDBY); } static int max6639_resume(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); struct max6639_data *data = dev_get_drvdata(dev); int ret; @@ -601,12 +564,8 @@ static int max6639_resume(struct device *dev) } } - ret = i2c_smbus_read_byte_data(client, MAX6639_REG_GCONFIG); - if (ret < 0) - return ret; - - return i2c_smbus_write_byte_data(client, - MAX6639_REG_GCONFIG, ret & ~MAX6639_GCONFIG_STANDBY); + return regmap_write_bits(data->regmap, MAX6639_REG_GCONFIG, MAX6639_GCONFIG_STANDBY, + ~MAX6639_GCONFIG_STANDBY); } static const struct i2c_device_id max6639_id[] = { -- cgit v1.2.3 From e0cd85dc666cb08e1bd313d560cb4eff4d04219e Mon Sep 17 00:00:00 2001 From: Aleksa Savic Date: Sat, 4 May 2024 11:25:01 +0200 Subject: hwmon: (corsair-cpro) Use a separate buffer for sending commands Introduce cmd_buffer, a separate buffer for storing only the command that is sent to the device. Before this separation, the existing buffer was shared for both the command and the report received in ccp_raw_event(), which was copied into it. However, because of hidraw, the raw event parsing may be triggered in the middle of sending a command, resulting in outputting gibberish to the device. Using a separate buffer resolves this. Fixes: 40c3a4454225 ("hwmon: add Corsair Commander Pro driver") Signed-off-by: Aleksa Savic Acked-by: Marius Zachmann Link: https://lore.kernel.org/r/20240504092504.24158-2-savicaleksa83@gmail.com Signed-off-by: Guenter Roeck --- drivers/hwmon/corsair-cpro.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/corsair-cpro.c b/drivers/hwmon/corsair-cpro.c index a284a02839fb..8d85f66f8143 100644 --- a/drivers/hwmon/corsair-cpro.c +++ b/drivers/hwmon/corsair-cpro.c @@ -79,6 +79,7 @@ struct ccp_device { struct device *hwmon_dev; struct completion wait_input_report; struct mutex mutex; /* whenever buffer is used, lock before send_usb_cmd */ + u8 *cmd_buffer; u8 *buffer; int target[6]; DECLARE_BITMAP(temp_cnct, NUM_TEMP_SENSORS); @@ -111,15 +112,15 @@ static int send_usb_cmd(struct ccp_device *ccp, u8 command, u8 byte1, u8 byte2, 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; + memset(ccp->cmd_buffer, 0x00, OUT_BUFFER_SIZE); + ccp->cmd_buffer[0] = command; + ccp->cmd_buffer[1] = byte1; + ccp->cmd_buffer[2] = byte2; + ccp->cmd_buffer[3] = byte3; reinit_completion(&ccp->wait_input_report); - ret = hid_hw_output_report(ccp->hdev, ccp->buffer, OUT_BUFFER_SIZE); + ret = hid_hw_output_report(ccp->hdev, ccp->cmd_buffer, OUT_BUFFER_SIZE); if (ret < 0) return ret; @@ -492,7 +493,11 @@ static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id) if (!ccp) return -ENOMEM; - ccp->buffer = devm_kmalloc(&hdev->dev, OUT_BUFFER_SIZE, GFP_KERNEL); + ccp->cmd_buffer = devm_kmalloc(&hdev->dev, OUT_BUFFER_SIZE, GFP_KERNEL); + if (!ccp->cmd_buffer) + return -ENOMEM; + + ccp->buffer = devm_kmalloc(&hdev->dev, IN_BUFFER_SIZE, GFP_KERNEL); if (!ccp->buffer) return -ENOMEM; -- cgit v1.2.3 From 3a034a7b0715eb51124a5263890b1ed39978ed3a Mon Sep 17 00:00:00 2001 From: Aleksa Savic Date: Sat, 4 May 2024 11:25:02 +0200 Subject: hwmon: (corsair-cpro) Use complete_all() instead of complete() in ccp_raw_event() In ccp_raw_event(), the ccp->wait_input_report completion is completed once. Since we're waiting for exactly one report in send_usb_cmd(), use complete_all() instead of complete() to mark the completion as spent. Fixes: 40c3a4454225 ("hwmon: add Corsair Commander Pro driver") Signed-off-by: Aleksa Savic Acked-by: Marius Zachmann Link: https://lore.kernel.org/r/20240504092504.24158-3-savicaleksa83@gmail.com Signed-off-by: Guenter Roeck --- drivers/hwmon/corsair-cpro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/corsair-cpro.c b/drivers/hwmon/corsair-cpro.c index 8d85f66f8143..6ab4d2478b1f 100644 --- a/drivers/hwmon/corsair-cpro.c +++ b/drivers/hwmon/corsair-cpro.c @@ -140,7 +140,7 @@ static int ccp_raw_event(struct hid_device *hdev, struct hid_report *report, u8 return 0; memcpy(ccp->buffer, data, min(IN_BUFFER_SIZE, size)); - complete(&ccp->wait_input_report); + complete_all(&ccp->wait_input_report); return 0; } -- cgit v1.2.3 From d02abd57e79469a026213f7f5827a98d909f236a Mon Sep 17 00:00:00 2001 From: Aleksa Savic Date: Sat, 4 May 2024 11:25:03 +0200 Subject: hwmon: (corsair-cpro) Protect ccp->wait_input_report with a spinlock Through hidraw, userspace can cause a status report to be sent from the device. The parsing in ccp_raw_event() may happen in parallel to a send_usb_cmd() call (which resets the completion for tracking the report) if it's running on a different CPU where bottom half interrupts are not disabled. Add a spinlock around the complete_all() in ccp_raw_event() and reinit_completion() in send_usb_cmd() to prevent race issues. Fixes: 40c3a4454225 ("hwmon: add Corsair Commander Pro driver") Signed-off-by: Aleksa Savic Acked-by: Marius Zachmann Link: https://lore.kernel.org/r/20240504092504.24158-4-savicaleksa83@gmail.com Signed-off-by: Guenter Roeck --- drivers/hwmon/corsair-cpro.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/corsair-cpro.c b/drivers/hwmon/corsair-cpro.c index 6ab4d2478b1f..3e63666a61bd 100644 --- a/drivers/hwmon/corsair-cpro.c +++ b/drivers/hwmon/corsair-cpro.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #define USB_VENDOR_ID_CORSAIR 0x1b1c @@ -77,6 +78,8 @@ struct ccp_device { struct hid_device *hdev; struct device *hwmon_dev; + /* For reinitializing the completion below */ + spinlock_t wait_input_report_lock; struct completion wait_input_report; struct mutex mutex; /* whenever buffer is used, lock before send_usb_cmd */ u8 *cmd_buffer; @@ -118,7 +121,15 @@ static int send_usb_cmd(struct ccp_device *ccp, u8 command, u8 byte1, u8 byte2, ccp->cmd_buffer[2] = byte2; ccp->cmd_buffer[3] = byte3; + /* + * Disable raw event parsing for a moment to safely reinitialize the + * completion. Reinit is done because hidraw could have triggered + * the raw event parsing and marked the ccp->wait_input_report + * completion as done. + */ + spin_lock_bh(&ccp->wait_input_report_lock); reinit_completion(&ccp->wait_input_report); + spin_unlock_bh(&ccp->wait_input_report_lock); ret = hid_hw_output_report(ccp->hdev, ccp->cmd_buffer, OUT_BUFFER_SIZE); if (ret < 0) @@ -136,11 +147,12 @@ static int ccp_raw_event(struct hid_device *hdev, struct hid_report *report, u8 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_all(&ccp->wait_input_report); + spin_lock(&ccp->wait_input_report_lock); + if (!completion_done(&ccp->wait_input_report)) { + memcpy(ccp->buffer, data, min(IN_BUFFER_SIZE, size)); + complete_all(&ccp->wait_input_report); + } + spin_unlock(&ccp->wait_input_report_lock); return 0; } @@ -515,7 +527,9 @@ static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id) ccp->hdev = hdev; hid_set_drvdata(hdev, ccp); + mutex_init(&ccp->mutex); + spin_lock_init(&ccp->wait_input_report_lock); init_completion(&ccp->wait_input_report); hid_device_io_start(hdev); -- cgit v1.2.3 From 346fe0ce1fd780038ca9e5bcb65aad54bae7c4d9 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 6 May 2024 10:59:16 -0500 Subject: hwmon: (adc128d818) simplify final return in probe The final return in adc128d818_probe() can be simplified by using PTR_ERR_OR_ZERO rather than an if statement. Suggested-by: Guenter Roeck Signed-off-by: David Lechner Acked-by: Guenter Roeck Link: https://lore.kernel.org/r/20240506-regulator-devm_regulator_get_enable_read_voltage-fixes-v1-2-356cdd152067@baylibre.com Signed-off-by: Mark Brown --- drivers/hwmon/adc128d818.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/adc128d818.c b/drivers/hwmon/adc128d818.c index 2a35acb011eb..321a61977396 100644 --- a/drivers/hwmon/adc128d818.c +++ b/drivers/hwmon/adc128d818.c @@ -475,10 +475,8 @@ static int adc128_probe(struct i2c_client *client) hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, data, adc128_groups); - if (IS_ERR(hwmon_dev)) - return PTR_ERR(hwmon_dev); - return 0; + return PTR_ERR_OR_ZERO(hwmon_dev); } static const struct i2c_device_id adc128_id[] = { -- cgit v1.2.3 From 1094360dc860e3578b3ec1889b05c88462ff189e Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sun, 28 Nov 2021 10:06:14 -0800 Subject: hwmon: (emc1403) Convert to with_info API Convert driver to register with the hwmon subsystem using devm_hwmon_device_register_with_info() instead of devm_hwmon_device_register_with_groups() to simplify the code and to reduce its size. As side effect, this also fixes a couple of overflow problems when writing limit and hysteresis registers. Cc: Lars Petter Mostad Tested-by: Lars Petter Mostad Signed-off-by: Guenter Roeck --- drivers/hwmon/emc1403.c | 623 ++++++++++++++++++++++++++---------------------- 1 file changed, 332 insertions(+), 291 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c index d370efd6f986..e656f0432a57 100644 --- a/drivers/hwmon/emc1403.c +++ b/drivers/hwmon/emc1403.c @@ -27,60 +27,26 @@ enum emc1403_chip { emc1402, emc1403, emc1404 }; struct thermal_data { + enum emc1403_chip chip; struct regmap *regmap; struct mutex mutex; - const struct attribute_group *groups[4]; }; -static ssize_t temp_show(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t power_state_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); struct thermal_data *data = dev_get_drvdata(dev); unsigned int val; int retval; - retval = regmap_read(data->regmap, sda->index, &val); + retval = regmap_read(data->regmap, 0x03, &val); if (retval < 0) return retval; - return sprintf(buf, "%d000\n", val); + return sprintf(buf, "%d\n", !!(val & BIT(6))); } -static ssize_t bit_show(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t power_state_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { - struct sensor_device_attribute_2 *sda = to_sensor_dev_attr_2(attr); - struct thermal_data *data = dev_get_drvdata(dev); - unsigned int val; - int retval; - - retval = regmap_read(data->regmap, sda->nr, &val); - if (retval < 0) - return retval; - return sprintf(buf, "%d\n", !!(val & sda->index)); -} - -static ssize_t temp_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); - struct thermal_data *data = dev_get_drvdata(dev); - unsigned long val; - int retval; - - if (kstrtoul(buf, 10, &val)) - return -EINVAL; - retval = regmap_write(data->regmap, sda->index, - DIV_ROUND_CLOSEST(val, 1000)); - if (retval < 0) - return retval; - return count; -} - -static ssize_t bit_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *sda = to_sensor_dev_attr_2(attr); struct thermal_data *data = dev_get_drvdata(dev); unsigned long val; int retval; @@ -88,233 +54,20 @@ static ssize_t bit_store(struct device *dev, struct device_attribute *attr, if (kstrtoul(buf, 10, &val)) return -EINVAL; - retval = regmap_update_bits(data->regmap, sda->nr, sda->index, - val ? sda->index : 0); + retval = regmap_update_bits(data->regmap, 0x03, BIT(6), + val ? BIT(6) : 0); if (retval < 0) return retval; return count; } -static ssize_t show_hyst_common(struct device *dev, - struct device_attribute *attr, char *buf, - bool is_min) -{ - struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); - struct thermal_data *data = dev_get_drvdata(dev); - struct regmap *regmap = data->regmap; - unsigned int limit; - unsigned int hyst; - int retval; - - retval = regmap_read(regmap, sda->index, &limit); - if (retval < 0) - return retval; - - retval = regmap_read(regmap, 0x21, &hyst); - if (retval < 0) - return retval; - - return sprintf(buf, "%d000\n", is_min ? limit + hyst : limit - hyst); -} - -static ssize_t hyst_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return show_hyst_common(dev, attr, buf, false); -} - -static ssize_t min_hyst_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return show_hyst_common(dev, attr, buf, true); -} - -static ssize_t hyst_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); - struct thermal_data *data = dev_get_drvdata(dev); - struct regmap *regmap = data->regmap; - unsigned int limit; - int retval; - int hyst; - unsigned long val; - - if (kstrtoul(buf, 10, &val)) - return -EINVAL; - - mutex_lock(&data->mutex); - retval = regmap_read(regmap, sda->index, &limit); - if (retval < 0) - goto fail; - - hyst = limit * 1000 - val; - hyst = clamp_val(DIV_ROUND_CLOSEST(hyst, 1000), 0, 255); - retval = regmap_write(regmap, 0x21, hyst); - if (retval == 0) - retval = count; -fail: - mutex_unlock(&data->mutex); - return retval; -} - -/* - * Sensors. We pass the actual i2c register to the methods. - */ - -static SENSOR_DEVICE_ATTR_RW(temp1_min, temp, 0x06); -static SENSOR_DEVICE_ATTR_RW(temp1_max, temp, 0x05); -static SENSOR_DEVICE_ATTR_RW(temp1_crit, temp, 0x20); -static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0x00); -static SENSOR_DEVICE_ATTR_2_RO(temp1_min_alarm, bit, 0x36, 0x01); -static SENSOR_DEVICE_ATTR_2_RO(temp1_max_alarm, bit, 0x35, 0x01); -static SENSOR_DEVICE_ATTR_2_RO(temp1_crit_alarm, bit, 0x37, 0x01); -static SENSOR_DEVICE_ATTR_RO(temp1_min_hyst, min_hyst, 0x06); -static SENSOR_DEVICE_ATTR_RO(temp1_max_hyst, hyst, 0x05); -static SENSOR_DEVICE_ATTR_RW(temp1_crit_hyst, hyst, 0x20); - -static SENSOR_DEVICE_ATTR_RW(temp2_min, temp, 0x08); -static SENSOR_DEVICE_ATTR_RW(temp2_max, temp, 0x07); -static SENSOR_DEVICE_ATTR_RW(temp2_crit, temp, 0x19); -static SENSOR_DEVICE_ATTR_RO(temp2_input, temp, 0x01); -static SENSOR_DEVICE_ATTR_2_RO(temp2_fault, bit, 0x1b, 0x02); -static SENSOR_DEVICE_ATTR_2_RO(temp2_min_alarm, bit, 0x36, 0x02); -static SENSOR_DEVICE_ATTR_2_RO(temp2_max_alarm, bit, 0x35, 0x02); -static SENSOR_DEVICE_ATTR_2_RO(temp2_crit_alarm, bit, 0x37, 0x02); -static SENSOR_DEVICE_ATTR_RO(temp2_min_hyst, min_hyst, 0x08); -static SENSOR_DEVICE_ATTR_RO(temp2_max_hyst, hyst, 0x07); -static SENSOR_DEVICE_ATTR_RO(temp2_crit_hyst, hyst, 0x19); - -static SENSOR_DEVICE_ATTR_RW(temp3_min, temp, 0x16); -static SENSOR_DEVICE_ATTR_RW(temp3_max, temp, 0x15); -static SENSOR_DEVICE_ATTR_RW(temp3_crit, temp, 0x1A); -static SENSOR_DEVICE_ATTR_RO(temp3_input, temp, 0x23); -static SENSOR_DEVICE_ATTR_2_RO(temp3_fault, bit, 0x1b, 0x04); -static SENSOR_DEVICE_ATTR_2_RO(temp3_min_alarm, bit, 0x36, 0x04); -static SENSOR_DEVICE_ATTR_2_RO(temp3_max_alarm, bit, 0x35, 0x04); -static SENSOR_DEVICE_ATTR_2_RO(temp3_crit_alarm, bit, 0x37, 0x04); -static SENSOR_DEVICE_ATTR_RO(temp3_min_hyst, min_hyst, 0x16); -static SENSOR_DEVICE_ATTR_RO(temp3_max_hyst, hyst, 0x15); -static SENSOR_DEVICE_ATTR_RO(temp3_crit_hyst, hyst, 0x1A); - -static SENSOR_DEVICE_ATTR_RW(temp4_min, temp, 0x2D); -static SENSOR_DEVICE_ATTR_RW(temp4_max, temp, 0x2C); -static SENSOR_DEVICE_ATTR_RW(temp4_crit, temp, 0x30); -static SENSOR_DEVICE_ATTR_RO(temp4_input, temp, 0x2A); -static SENSOR_DEVICE_ATTR_2_RO(temp4_fault, bit, 0x1b, 0x08); -static SENSOR_DEVICE_ATTR_2_RO(temp4_min_alarm, bit, 0x36, 0x08); -static SENSOR_DEVICE_ATTR_2_RO(temp4_max_alarm, bit, 0x35, 0x08); -static SENSOR_DEVICE_ATTR_2_RO(temp4_crit_alarm, bit, 0x37, 0x08); -static SENSOR_DEVICE_ATTR_RO(temp4_min_hyst, min_hyst, 0x2D); -static SENSOR_DEVICE_ATTR_RO(temp4_max_hyst, hyst, 0x2C); -static SENSOR_DEVICE_ATTR_RO(temp4_crit_hyst, hyst, 0x30); - -static SENSOR_DEVICE_ATTR_2_RW(power_state, bit, 0x03, 0x40); - -static struct attribute *emc1402_attrs[] = { - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_crit.dev_attr.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_min_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, - - &sensor_dev_attr_temp2_min.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp2_crit.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_min_hyst.dev_attr.attr, - &sensor_dev_attr_temp2_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr, - - &sensor_dev_attr_power_state.dev_attr.attr, - NULL -}; - -static const struct attribute_group emc1402_group = { - .attrs = emc1402_attrs, -}; +static DEVICE_ATTR_RW(power_state); static struct attribute *emc1403_attrs[] = { - &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, - - &sensor_dev_attr_temp2_fault.dev_attr.attr, - &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, - - &sensor_dev_attr_temp3_min.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp3_crit.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp3_fault.dev_attr.attr, - &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_min_hyst.dev_attr.attr, - &sensor_dev_attr_temp3_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp3_crit_hyst.dev_attr.attr, - NULL -}; - -static const struct attribute_group emc1403_group = { - .attrs = emc1403_attrs, -}; - -static struct attribute *emc1404_attrs[] = { - &sensor_dev_attr_temp4_min.dev_attr.attr, - &sensor_dev_attr_temp4_max.dev_attr.attr, - &sensor_dev_attr_temp4_crit.dev_attr.attr, - &sensor_dev_attr_temp4_input.dev_attr.attr, - &sensor_dev_attr_temp4_fault.dev_attr.attr, - &sensor_dev_attr_temp4_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp4_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp4_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp4_min_hyst.dev_attr.attr, - &sensor_dev_attr_temp4_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp4_crit_hyst.dev_attr.attr, + &dev_attr_power_state.attr, NULL }; - -static const struct attribute_group emc1404_group = { - .attrs = emc1404_attrs, -}; - -/* - * EMC14x2 uses a different register and different bits to report alarm and - * fault status. For simplicity, provide a separate attribute group for this - * chip series. - * Since we can not re-use the same attribute names, create a separate attribute - * array. - */ -static struct sensor_device_attribute_2 emc1402_alarms[] = { - SENSOR_ATTR_2_RO(temp1_min_alarm, bit, 0x02, 0x20), - SENSOR_ATTR_2_RO(temp1_max_alarm, bit, 0x02, 0x40), - SENSOR_ATTR_2_RO(temp1_crit_alarm, bit, 0x02, 0x01), - - SENSOR_ATTR_2_RO(temp2_fault, bit, 0x02, 0x04), - SENSOR_ATTR_2_RO(temp2_min_alarm, bit, 0x02, 0x08), - SENSOR_ATTR_2_RO(temp2_max_alarm, bit, 0x02, 0x10), - SENSOR_ATTR_2_RO(temp2_crit_alarm, bit, 0x02, 0x02), -}; - -static struct attribute *emc1402_alarm_attrs[] = { - &emc1402_alarms[0].dev_attr.attr, - &emc1402_alarms[1].dev_attr.attr, - &emc1402_alarms[2].dev_attr.attr, - &emc1402_alarms[3].dev_attr.attr, - &emc1402_alarms[4].dev_attr.attr, - &emc1402_alarms[5].dev_attr.attr, - &emc1402_alarms[6].dev_attr.attr, - NULL, -}; - -static const struct attribute_group emc1402_alarm_group = { - .attrs = emc1402_alarm_attrs, -}; +ATTRIBUTE_GROUPS(emc1403); static int emc1403_detect(struct i2c_client *client, struct i2c_board_info *info) @@ -389,51 +142,310 @@ static const struct regmap_config emc1403_regmap_config = { .volatile_reg = emc1403_regmap_is_volatile, }; -static const struct i2c_device_id emc1403_idtable[]; +enum emc1403_reg_map {temp_min, temp_max, temp_crit, temp_input}; -static int emc1403_probe(struct i2c_client *client) +static u8 ema1403_temp_map[] = { + [hwmon_temp_min] = temp_min, + [hwmon_temp_max] = temp_max, + [hwmon_temp_crit] = temp_crit, + [hwmon_temp_input] = temp_input, +}; + +static u8 emc1403_temp_regs[][4] = { + [0] = { + [temp_min] = 0x06, + [temp_max] = 0x05, + [temp_crit] = 0x20, + [temp_input] = 0x00, + }, + [1] = { + [temp_min] = 0x08, + [temp_max] = 0x07, + [temp_crit] = 0x19, + [temp_input] = 0x01, + }, + [2] = { + [temp_min] = 0x16, + [temp_max] = 0x15, + [temp_crit] = 0x1a, + [temp_input] = 0x23, + }, + [3] = { + [temp_min] = 0x2d, + [temp_max] = 0x2c, + [temp_crit] = 0x30, + [temp_input] = 0x2a, + }, +}; + +static int __emc1403_get_temp(struct thermal_data *data, int channel, + enum emc1403_reg_map map, long *val) { - struct thermal_data *data; - struct device *hwmon_dev; - const struct i2c_device_id *id = i2c_match_id(emc1403_idtable, client); + unsigned int regval; + int ret; - data = devm_kzalloc(&client->dev, sizeof(struct thermal_data), - GFP_KERNEL); - if (data == NULL) - return -ENOMEM; + ret = regmap_read(data->regmap, emc1403_temp_regs[channel][map], ®val); + if (ret < 0) + return ret; + *val = regval * 1000; - data->regmap = devm_regmap_init_i2c(client, &emc1403_regmap_config); - if (IS_ERR(data->regmap)) - return PTR_ERR(data->regmap); + return 0; +} - mutex_init(&data->mutex); +static int emc1403_get_temp(struct thermal_data *data, int channel, + enum emc1403_reg_map map, long *val) +{ + int ret; + + mutex_lock(&data->mutex); + ret = __emc1403_get_temp(data, channel, map, val); + mutex_unlock(&data->mutex); + + return ret; +} + +static int emc1403_get_hyst(struct thermal_data *data, int channel, + enum emc1403_reg_map map, long *val) +{ + int hyst, ret; + long limit; + + mutex_lock(&data->mutex); + ret = __emc1403_get_temp(data, channel, map, &limit); + if (ret < 0) + goto unlock; + ret = regmap_read(data->regmap, 0x21, &hyst); + if (ret < 0) + goto unlock; + if (map == temp_min) + *val = limit + hyst * 1000; + else + *val = limit - hyst * 1000; +unlock: + mutex_unlock(&data->mutex); + return ret; +} + +static int emc1403_temp_read(struct thermal_data *data, u32 attr, int channel, long *val) +{ + unsigned int regval; + int ret; + + switch (attr) { + case hwmon_temp_min: + case hwmon_temp_max: + case hwmon_temp_crit: + case hwmon_temp_input: + ret = emc1403_get_temp(data, channel, ema1403_temp_map[attr], val); + break; + case hwmon_temp_min_hyst: + ret = emc1403_get_hyst(data, channel, temp_min, val); + break; + case hwmon_temp_max_hyst: + ret = emc1403_get_hyst(data, channel, temp_max, val); + break; + case hwmon_temp_crit_hyst: + ret = emc1403_get_hyst(data, channel, temp_crit, val); + break; + case hwmon_temp_min_alarm: + if (data->chip == emc1402) { + ret = regmap_read(data->regmap, 0x02, ®val); + if (ret < 0) + break; + *val = !!(regval & BIT(5 - 2 * channel)); + } else { + ret = regmap_read(data->regmap, 0x36, ®val); + if (ret < 0) + break; + *val = !!(regval & BIT(channel)); + } + break; + case hwmon_temp_max_alarm: + if (data->chip == emc1402) { + ret = regmap_read(data->regmap, 0x02, ®val); + if (ret < 0) + break; + *val = !!(regval & BIT(6 - 2 * channel)); + } else { + ret = regmap_read(data->regmap, 0x35, ®val); + if (ret < 0) + break; + *val = !!(regval & BIT(channel)); + } + break; + case hwmon_temp_crit_alarm: + if (data->chip == emc1402) { + ret = regmap_read(data->regmap, 0x02, ®val); + if (ret < 0) + break; + *val = !!(regval & BIT(channel)); + } else { + ret = regmap_read(data->regmap, 0x37, ®val); + if (ret < 0) + break; + *val = !!(regval & BIT(channel)); + } + break; + case hwmon_temp_fault: + ret = regmap_read(data->regmap, 0x1b, ®val); + if (ret < 0) + break; + *val = !!(regval & BIT(channel)); + break; + default: + return -EOPNOTSUPP; + } + return ret; +} + +static int emc1403_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *val) +{ + struct thermal_data *data = dev_get_drvdata(dev); - switch (id->driver_data) { - case emc1404: - data->groups[2] = &emc1404_group; - fallthrough; - case emc1403: - data->groups[1] = &emc1403_group; - fallthrough; - case emc1402: - data->groups[0] = &emc1402_group; + switch (type) { + case hwmon_temp: + return emc1403_temp_read(data, attr, channel, val); + default: + return -EOPNOTSUPP; } +} - if (id->driver_data == emc1402) - data->groups[1] = &emc1402_alarm_group; +static int emc1403_set_hyst(struct thermal_data *data, long val) +{ + int hyst, ret; + long limit; - hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev, - client->name, data, - data->groups); - if (IS_ERR(hwmon_dev)) - return PTR_ERR(hwmon_dev); + val = clamp_val(val, 0, 255000); - dev_info(&client->dev, "%s Thermal chip found\n", id->name); - return 0; + mutex_lock(&data->mutex); + ret = __emc1403_get_temp(data, 0, temp_crit, &limit); + if (ret < 0) + goto unlock; + + hyst = limit - val; + hyst = clamp_val(DIV_ROUND_CLOSEST(hyst, 1000), 0, 255); + ret = regmap_write(data->regmap, 0x21, hyst); +unlock: + mutex_unlock(&data->mutex); + return ret; } -static const unsigned short emc1403_address_list[] = { - 0x18, 0x1c, 0x29, 0x3c, 0x4c, 0x4d, 0x5c, I2C_CLIENT_END +static int emc1403_set_temp(struct thermal_data *data, int channel, + enum emc1403_reg_map map, long val) +{ + unsigned int regval; + int ret; + + val = clamp_val(val, 0, 255000); + + mutex_lock(&data->mutex); + regval = DIV_ROUND_CLOSEST(val, 1000); + ret = regmap_write(data->regmap, emc1403_temp_regs[channel][map], regval); + mutex_unlock(&data->mutex); + return ret; +} + +static int emc1403_temp_write(struct thermal_data *data, u32 attr, int channel, long val) +{ + switch (attr) { + case hwmon_temp_min: + case hwmon_temp_max: + case hwmon_temp_crit: + return emc1403_set_temp(data, channel, ema1403_temp_map[attr], val); + case hwmon_temp_crit_hyst: + return emc1403_set_hyst(data, val); + default: + return -EOPNOTSUPP; + } +} + +static int emc1403_write(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long val) +{ + struct thermal_data *data = dev_get_drvdata(dev); + + switch (type) { + case hwmon_temp: + return emc1403_temp_write(data, attr, channel, val); + default: + return -EOPNOTSUPP; + } +} + +static umode_t emc1403_temp_is_visible(const void *_data, u32 attr, int channel) +{ + const struct thermal_data *data = _data; + + if (data->chip == emc1402 && channel > 1) + return 0; + if (data->chip == emc1403 && channel > 2) + return 0; + + switch (attr) { + case hwmon_temp_input: + case hwmon_temp_min_alarm: + case hwmon_temp_max_alarm: + case hwmon_temp_crit_alarm: + case hwmon_temp_fault: + case hwmon_temp_min_hyst: + case hwmon_temp_max_hyst: + return 0444; + case hwmon_temp_min: + case hwmon_temp_max: + case hwmon_temp_crit: + return 0644; + case hwmon_temp_crit_hyst: + if (channel == 0) + return 0644; + return 0444; + default: + return 0; + } +} + +static umode_t emc1403_is_visible(const void *data, enum hwmon_sensor_types type, + u32 attr, int channel) +{ + switch (type) { + case hwmon_temp: + return emc1403_temp_is_visible(data, attr, channel); + default: + return 0; + } +} + +static const struct hwmon_channel_info * const emc1403_info[] = { + HWMON_CHANNEL_INFO(temp, + HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX | + HWMON_T_CRIT | HWMON_T_MIN_HYST | HWMON_T_MAX_HYST | + HWMON_T_CRIT_HYST | HWMON_T_MIN_ALARM | + HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM, + HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX | + HWMON_T_CRIT | HWMON_T_MIN_HYST | HWMON_T_MAX_HYST | + HWMON_T_CRIT_HYST | HWMON_T_MIN_ALARM | + HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM | HWMON_T_FAULT, + HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX | + HWMON_T_CRIT | HWMON_T_MIN_HYST | HWMON_T_MAX_HYST | + HWMON_T_CRIT_HYST | HWMON_T_MIN_ALARM | + HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM | HWMON_T_FAULT, + HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX | + HWMON_T_CRIT | HWMON_T_MIN_HYST | HWMON_T_MAX_HYST | + HWMON_T_CRIT_HYST | HWMON_T_MIN_ALARM | + HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM | HWMON_T_FAULT + ), + NULL +}; + +static const struct hwmon_ops emc1403_hwmon_ops = { + .is_visible = emc1403_is_visible, + .read = emc1403_read, + .write = emc1403_write, +}; + +static const struct hwmon_chip_info emc1403_chip_info = { + .ops = &emc1403_hwmon_ops, + .info = emc1403_info, }; /* Last digit of chip name indicates number of channels */ @@ -452,6 +464,35 @@ static const struct i2c_device_id emc1403_idtable[] = { }; MODULE_DEVICE_TABLE(i2c, emc1403_idtable); +static int emc1403_probe(struct i2c_client *client) +{ + struct thermal_data *data; + struct device *hwmon_dev; + const struct i2c_device_id *id = i2c_match_id(emc1403_idtable, client); + + data = devm_kzalloc(&client->dev, sizeof(struct thermal_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->chip = id->driver_data; + data->regmap = devm_regmap_init_i2c(client, &emc1403_regmap_config); + if (IS_ERR(data->regmap)) + return PTR_ERR(data->regmap); + + mutex_init(&data->mutex); + + hwmon_dev = devm_hwmon_device_register_with_info(&client->dev, + client->name, data, + &emc1403_chip_info, + emc1403_groups); + return PTR_ERR_OR_ZERO(hwmon_dev); +} + +static const unsigned short emc1403_address_list[] = { + 0x18, 0x1c, 0x29, 0x3c, 0x4c, 0x4d, 0x5c, I2C_CLIENT_END +}; + static struct i2c_driver sensor_emc1403 = { .class = I2C_CLASS_HWMON, .driver = { -- cgit v1.2.3 From e77b204ad4d01d3aee5e18fe33dc6d7a09953308 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Thu, 2 May 2024 21:53:55 -0700 Subject: hwmon: (emc1403) Support 11 bit accuracy Various temperature and limit registers support 11 bit accuracy. Add support for it. Cc: Lars Petter Mostad Tested-by: Lars Petter Mostad Signed-off-by: Guenter Roeck --- drivers/hwmon/emc1403.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 3 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c index e656f0432a57..e53bb4d8bc1b 100644 --- a/drivers/hwmon/emc1403.c +++ b/drivers/hwmon/emc1403.c @@ -178,17 +178,52 @@ static u8 emc1403_temp_regs[][4] = { }, }; +static s8 emc1403_temp_regs_low[][4] = { + [0] = { + [temp_min] = -1, + [temp_max] = -1, + [temp_crit] = -1, + [temp_input] = 0x29, + }, + [1] = { + [temp_min] = 0x14, + [temp_max] = 0x13, + [temp_crit] = -1, + [temp_input] = 0x10, + }, + [2] = { + [temp_min] = 0x18, + [temp_max] = 0x17, + [temp_crit] = -1, + [temp_input] = 0x24, + }, + [3] = { + [temp_min] = 0x2f, + [temp_max] = 0x2e, + [temp_crit] = -1, + [temp_input] = 0x2b, + }, +}; + static int __emc1403_get_temp(struct thermal_data *data, int channel, enum emc1403_reg_map map, long *val) { unsigned int regval; int ret; + s8 reg; ret = regmap_read(data->regmap, emc1403_temp_regs[channel][map], ®val); if (ret < 0) return ret; *val = regval * 1000; + reg = emc1403_temp_regs_low[channel][map]; + if (reg >= 0) { + ret = regmap_read(data->regmap, reg, ®val); + if (ret < 0) + return ret; + *val += (regval >> 5) * 125; + } return 0; } @@ -336,12 +371,26 @@ static int emc1403_set_temp(struct thermal_data *data, int channel, { unsigned int regval; int ret; + u8 regh; + s8 regl; - val = clamp_val(val, 0, 255000); + regh = emc1403_temp_regs[channel][map]; + regl = emc1403_temp_regs_low[channel][map]; mutex_lock(&data->mutex); - regval = DIV_ROUND_CLOSEST(val, 1000); - ret = regmap_write(data->regmap, emc1403_temp_regs[channel][map], regval); + if (regl >= 0) { + val = clamp_val(val, 0, 255875); + regval = DIV_ROUND_CLOSEST(val, 125); + ret = regmap_write(data->regmap, regh, regval >> 3); + if (ret < 0) + goto unlock; + ret = regmap_write(data->regmap, regl, (regval & 0x07) << 5); + } else { + val = clamp_val(val, 0, 255000); + regval = DIV_ROUND_CLOSEST(val, 1000); + ret = regmap_write(data->regmap, regh, regval); + } +unlock: mutex_unlock(&data->mutex); return ret; } -- cgit v1.2.3 From 6a8157812f5b486d1fdabeefa070d75ae49220ee Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Fri, 3 May 2024 08:04:43 -0700 Subject: hwmon: (emc1403) Add support for conversion interval configuration The chips supported by the emc1403 driver support configurable conversion rates. Add support for it. Cc: Lars Petter Mostad Tested-by: Lars Petter Mostad Signed-off-by: Guenter Roeck --- drivers/hwmon/emc1403.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c index e53bb4d8bc1b..43322bb9aaa1 100644 --- a/drivers/hwmon/emc1403.c +++ b/drivers/hwmon/emc1403.c @@ -19,6 +19,7 @@ #include #include #include +#include #define THERMAL_PID_REG 0xfd #define THERMAL_SMSC_ID_REG 0xfe @@ -333,6 +334,31 @@ static int emc1403_temp_read(struct thermal_data *data, u32 attr, int channel, l return ret; } +static int emc1403_get_convrate(struct thermal_data *data, long *val) +{ + unsigned int convrate; + int ret; + + ret = regmap_read(data->regmap, 0x04, &convrate); + if (ret < 0) + return ret; + if (convrate > 10) + convrate = 4; + + *val = 16000 >> convrate; + return 0; +} + +static int emc1403_chip_read(struct thermal_data *data, u32 attr, long *val) +{ + switch (attr) { + case hwmon_chip_update_interval: + return emc1403_get_convrate(data, val); + default: + return -EOPNOTSUPP; + } +} + static int emc1403_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, long *val) { @@ -341,6 +367,8 @@ static int emc1403_read(struct device *dev, enum hwmon_sensor_types type, switch (type) { case hwmon_temp: return emc1403_temp_read(data, attr, channel, val); + case hwmon_chip: + return emc1403_chip_read(data, attr, val); default: return -EOPNOTSUPP; } @@ -409,6 +437,30 @@ static int emc1403_temp_write(struct thermal_data *data, u32 attr, int channel, } } +/* Lookup table for temperature conversion times in msec */ +static const u16 ina3221_conv_time[] = { + 16000, 8000, 4000, 2000, 1000, 500, 250, 125, 62, 31, 16 +}; + +static int emc1403_set_convrate(struct thermal_data *data, unsigned int interval) +{ + int convrate; + + convrate = find_closest_descending(interval, ina3221_conv_time, + ARRAY_SIZE(ina3221_conv_time)); + return regmap_write(data->regmap, 0x04, convrate); +} + +static int emc1403_chip_write(struct thermal_data *data, u32 attr, long val) +{ + switch (attr) { + case hwmon_chip_update_interval: + return emc1403_set_convrate(data, clamp_val(val, 0, 100000)); + default: + return -EOPNOTSUPP; + } +} + static int emc1403_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, long val) { @@ -417,6 +469,8 @@ static int emc1403_write(struct device *dev, enum hwmon_sensor_types type, switch (type) { case hwmon_temp: return emc1403_temp_write(data, attr, channel, val); + case hwmon_chip: + return emc1403_chip_write(data, attr, val); default: return -EOPNOTSUPP; } @@ -453,18 +507,31 @@ static umode_t emc1403_temp_is_visible(const void *_data, u32 attr, int channel) } } +static umode_t emc1403_chip_is_visible(const void *_data, u32 attr) +{ + switch (attr) { + case hwmon_chip_update_interval: + return 0644; + default: + return 0; + } +} + static umode_t emc1403_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr, int channel) { switch (type) { case hwmon_temp: return emc1403_temp_is_visible(data, attr, channel); + case hwmon_chip: + return emc1403_chip_is_visible(data, attr); default: return 0; } } static const struct hwmon_channel_info * const emc1403_info[] = { + HWMON_CHANNEL_INFO(chip, HWMON_C_UPDATE_INTERVAL), HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX | HWMON_T_CRIT | HWMON_T_MIN_HYST | HWMON_T_MAX_HYST | -- cgit v1.2.3 From 26e8383b116d0dbe74e28f86646563ab46d66d83 Mon Sep 17 00:00:00 2001 From: Lakshmi Yadlapati Date: Tue, 7 May 2024 14:46:03 -0500 Subject: hwmon: (pmbus/ucd9000) Increase delay from 250 to 500us Following the failure observed with a delay of 250us, experiments were conducted with various delays. It was found that a delay of 350us effectively mitigated the issue. To provide a more optimal solution while still allowing a margin for stability, the delay is being adjusted to 500us. Signed-off-by: Lakshmi Yadlapati Link: https://lore.kernel.org/r/20240507194603.1305750-1-lakshmiy@us.ibm.com Fixes: 8d655e6523764 ("hwmon: (ucd90320) Add minimum delay between bus accesses") Reviewed-by: Eddie James Cc: stable@vger.kernel.org Signed-off-by: Guenter Roeck --- drivers/hwmon/pmbus/ucd9000.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/pmbus/ucd9000.c b/drivers/hwmon/pmbus/ucd9000.c index 8d9d422450e5..d817c719b90b 100644 --- a/drivers/hwmon/pmbus/ucd9000.c +++ b/drivers/hwmon/pmbus/ucd9000.c @@ -80,11 +80,11 @@ struct ucd9000_debugfs_entry { * It has been observed that the UCD90320 randomly fails register access when * doing another access right on the back of a register write. To mitigate this * make sure that there is a minimum delay between a write access and the - * following access. The 250us is based on experimental data. At a delay of - * 200us the issue seems to go away. Add a bit of extra margin to allow for + * following access. The 500 is based on experimental data. At a delay of + * 350us the issue seems to go away. Add a bit of extra margin to allow for * system to system differences. */ -#define UCD90320_WAIT_DELAY_US 250 +#define UCD90320_WAIT_DELAY_US 500 static inline void ucd90320_wait(const struct ucd9000_data *data) { -- cgit v1.2.3 From 2fa365974c3eb97f29ff2dbeff3e9011170e492c Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 8 May 2024 09:20:26 +0200 Subject: hwmon: Drop explicit initialization of struct i2c_device_id::driver_data to 0 (part 2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These drivers don't use the driver_data member of struct i2c_device_id, so don't explicitly initialize this member. This prepares putting driver_data in an anonymous union which requires either no initialization or named designators. But it's also a nice cleanup on its own. This is a follow up to commit d8a66f3621c2 ("hwmon: Drop explicit initialization of struct i2c_device_id::driver_data to 0") which I created before identifying a few corner cases in my conversion script. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20240508072027.2119857-2-u.kleine-koenig@pengutronix.de Signed-off-by: Guenter Roeck --- drivers/hwmon/lm87.c | 2 +- drivers/hwmon/lm95241.c | 2 +- drivers/hwmon/max6621.c | 2 +- drivers/hwmon/pmbus/max15301.c | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c index 03964127a12a..d2d970e73c61 100644 --- a/drivers/hwmon/lm87.c +++ b/drivers/hwmon/lm87.c @@ -976,7 +976,7 @@ static int lm87_probe(struct i2c_client *client) static const struct i2c_device_id lm87_id[] = { { "lm87" }, - { "adm1024", 0 }, + { "adm1024" }, { } }; MODULE_DEVICE_TABLE(i2c, lm87_id); diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c index 4ad69a2de105..cad0a0ff8416 100644 --- a/drivers/hwmon/lm95241.c +++ b/drivers/hwmon/lm95241.c @@ -458,7 +458,7 @@ static int lm95241_probe(struct i2c_client *client) /* Driver data (common to all clients) */ static const struct i2c_device_id lm95241_id[] = { { "lm95231" }, - { "lm95241", 0 }, + { "lm95241" }, { } }; MODULE_DEVICE_TABLE(i2c, lm95241_id); diff --git a/drivers/hwmon/max6621.c b/drivers/hwmon/max6621.c index 05426cde0e36..a7066f3a0bb4 100644 --- a/drivers/hwmon/max6621.c +++ b/drivers/hwmon/max6621.c @@ -537,7 +537,7 @@ static int max6621_probe(struct i2c_client *client) } static const struct i2c_device_id max6621_id[] = { - { MAX6621_DRV_NAME, 0 }, + { MAX6621_DRV_NAME }, { } }; MODULE_DEVICE_TABLE(i2c, max6621_id); diff --git a/drivers/hwmon/pmbus/max15301.c b/drivers/hwmon/pmbus/max15301.c index c79cdf10bbec..986404fe6a31 100644 --- a/drivers/hwmon/pmbus/max15301.c +++ b/drivers/hwmon/pmbus/max15301.c @@ -23,8 +23,8 @@ #include "pmbus.h" static const struct i2c_device_id max15301_id[] = { - {"bmr461"}, - {"max15301", 0}, + { "bmr461" }, + { "max15301" }, {} }; MODULE_DEVICE_TABLE(i2c, max15301_id); -- cgit v1.2.3 From c82337843dd7c0723e7ce2b86e5ed89d71f1c7c3 Mon Sep 17 00:00:00 2001 From: Lars Petter Mostad Date: Fri, 10 May 2024 16:28:24 +0200 Subject: hwmon: (emc1403) Add support for EMC1428 and EMC1438. EMC1428 and EMC1438 are similar to EMC14xx, but have eight temperature channels, as well as signed data and limit registers. Chips currently supported by this driver have unsigned registers only. Signed-off-by: Lars Petter Mostad Link: https://lore.kernel.org/r/20240510142824.824332-1-lars.petter.mostad@appear.net Signed-off-by: Guenter Roeck --- Documentation/hwmon/emc1403.rst | 17 +++++- drivers/hwmon/emc1403.c | 121 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 124 insertions(+), 14 deletions(-) (limited to 'drivers/hwmon') diff --git a/Documentation/hwmon/emc1403.rst b/Documentation/hwmon/emc1403.rst index 0de9616b24ed..57f833b1a800 100644 --- a/Documentation/hwmon/emc1403.rst +++ b/Documentation/hwmon/emc1403.rst @@ -45,6 +45,17 @@ Supported chips: - https://ww1.microchip.com/downloads/en/DeviceDoc/1423_1424.pdf + * SMSC / Microchip EMC1428, EMC1438 + + Addresses scanned: I2C 0x18, 0x4c, 0x4d + + Prefix: 'emc1428', 'emc1438' + + Datasheets: + + - https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/20005275A.pdf + - https://ww1.microchip.com/downloads/en/DeviceDoc/EMC1438%20DS%20Rev.%201.0%20(04-29-10).pdf + Author: Kalhan Trisal type, "emc1424", I2C_NAME_SIZE); break; + case 0x29: + strscpy(info->type, "emc1428", I2C_NAME_SIZE); + break; + case 0x59: + strscpy(info->type, "emc1438", I2C_NAME_SIZE); + break; case 0x60: strscpy(info->type, "emc1442", I2C_NAME_SIZE); break; @@ -130,6 +136,14 @@ static bool emc1403_regmap_is_volatile(struct device *dev, unsigned int reg) case 0x35: /* high limit status */ case 0x36: /* low limit status */ case 0x37: /* therm limit status */ + case 0x41: /* external diode 4 high byte */ + case 0x42: /* external diode 4 low byte */ + case 0x43: /* external diode 5 high byte */ + case 0x44: /* external diode 5 low byte */ + case 0x45: /* external diode 6 high byte */ + case 0x46: /* external diode 6 low byte */ + case 0x47: /* external diode 7 high byte */ + case 0x48: /* external diode 7 low byte */ return true; default: return false; @@ -177,6 +191,30 @@ static u8 emc1403_temp_regs[][4] = { [temp_crit] = 0x30, [temp_input] = 0x2a, }, + [4] = { + [temp_min] = 0x51, + [temp_max] = 0x50, + [temp_crit] = 0x64, + [temp_input] = 0x41, + }, + [5] = { + [temp_min] = 0x55, + [temp_max] = 0x54, + [temp_crit] = 0x65, + [temp_input] = 0x43 + }, + [6] = { + [temp_min] = 0x59, + [temp_max] = 0x58, + [temp_crit] = 0x66, + [temp_input] = 0x45, + }, + [7] = { + [temp_min] = 0x5d, + [temp_max] = 0x5c, + [temp_crit] = 0x67, + [temp_input] = 0x47, + }, }; static s8 emc1403_temp_regs_low[][4] = { @@ -204,27 +242,56 @@ static s8 emc1403_temp_regs_low[][4] = { [temp_crit] = -1, [temp_input] = 0x2b, }, + [4] = { + [temp_min] = 0x53, + [temp_max] = 0x52, + [temp_crit] = -1, + [temp_input] = 0x42, + }, + [5] = { + [temp_min] = 0x57, + [temp_max] = 0x56, + [temp_crit] = -1, + [temp_input] = 0x44, + }, + [6] = { + [temp_min] = 0x5b, + [temp_max] = 0x5a, + [temp_crit] = -1, + [temp_input] = 0x46, + }, + [7] = { + [temp_min] = 0x5f, + [temp_max] = 0x5e, + [temp_crit] = -1, + [temp_input] = 0x48, + }, }; static int __emc1403_get_temp(struct thermal_data *data, int channel, enum emc1403_reg_map map, long *val) { - unsigned int regval; + unsigned int regvalh; + unsigned int regvall = 0; int ret; s8 reg; - ret = regmap_read(data->regmap, emc1403_temp_regs[channel][map], ®val); + ret = regmap_read(data->regmap, emc1403_temp_regs[channel][map], ®valh); if (ret < 0) return ret; - *val = regval * 1000; reg = emc1403_temp_regs_low[channel][map]; if (reg >= 0) { - ret = regmap_read(data->regmap, reg, ®val); + ret = regmap_read(data->regmap, reg, ®vall); if (ret < 0) return ret; - *val += (regval >> 5) * 125; } + + if (data->chip == emc1428) + *val = sign_extend32((regvalh << 3) | (regvall >> 5), 10) * 125; + else + *val = ((regvalh << 3) | (regvall >> 5)) * 125; + return 0; } @@ -379,7 +446,10 @@ static int emc1403_set_hyst(struct thermal_data *data, long val) int hyst, ret; long limit; - val = clamp_val(val, 0, 255000); + if (data->chip == emc1428) + val = clamp_val(val, -128000, 127000); + else + val = clamp_val(val, 0, 255000); mutex_lock(&data->mutex); ret = __emc1403_get_temp(data, 0, temp_crit, &limit); @@ -387,7 +457,10 @@ static int emc1403_set_hyst(struct thermal_data *data, long val) goto unlock; hyst = limit - val; - hyst = clamp_val(DIV_ROUND_CLOSEST(hyst, 1000), 0, 255); + if (data->chip == emc1428) + hyst = clamp_val(DIV_ROUND_CLOSEST(hyst, 1000), 0, 127); + else + hyst = clamp_val(DIV_ROUND_CLOSEST(hyst, 1000), 0, 255); ret = regmap_write(data->regmap, 0x21, hyst); unlock: mutex_unlock(&data->mutex); @@ -407,14 +480,20 @@ static int emc1403_set_temp(struct thermal_data *data, int channel, mutex_lock(&data->mutex); if (regl >= 0) { - val = clamp_val(val, 0, 255875); + if (data->chip == emc1428) + val = clamp_val(val, -128000, 127875); + else + val = clamp_val(val, 0, 255875); regval = DIV_ROUND_CLOSEST(val, 125); - ret = regmap_write(data->regmap, regh, regval >> 3); + ret = regmap_write(data->regmap, regh, (regval >> 3) & 0xff); if (ret < 0) goto unlock; ret = regmap_write(data->regmap, regl, (regval & 0x07) << 5); } else { - val = clamp_val(val, 0, 255000); + if (data->chip == emc1428) + val = clamp_val(val, -128000, 127000); + else + val = clamp_val(val, 0, 255000); regval = DIV_ROUND_CLOSEST(val, 1000); ret = regmap_write(data->regmap, regh, regval); } @@ -484,6 +563,8 @@ static umode_t emc1403_temp_is_visible(const void *_data, u32 attr, int channel) return 0; if (data->chip == emc1403 && channel > 2) return 0; + if (data->chip != emc1428 && channel > 3) + return 0; switch (attr) { case hwmon_temp_input: @@ -548,6 +629,22 @@ static const struct hwmon_channel_info * const emc1403_info[] = { HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX | HWMON_T_CRIT | HWMON_T_MIN_HYST | HWMON_T_MAX_HYST | HWMON_T_CRIT_HYST | HWMON_T_MIN_ALARM | + HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM | HWMON_T_FAULT, + HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX | + HWMON_T_CRIT | HWMON_T_MIN_HYST | HWMON_T_MAX_HYST | + HWMON_T_CRIT_HYST | HWMON_T_MIN_ALARM | + HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM | HWMON_T_FAULT, + HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX | + HWMON_T_CRIT | HWMON_T_MIN_HYST | HWMON_T_MAX_HYST | + HWMON_T_CRIT_HYST | HWMON_T_MIN_ALARM | + HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM | HWMON_T_FAULT, + HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX | + HWMON_T_CRIT | HWMON_T_MIN_HYST | HWMON_T_MAX_HYST | + HWMON_T_CRIT_HYST | HWMON_T_MIN_ALARM | + HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM | HWMON_T_FAULT, + HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX | + HWMON_T_CRIT | HWMON_T_MIN_HYST | HWMON_T_MAX_HYST | + HWMON_T_CRIT_HYST | HWMON_T_MIN_ALARM | HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM | HWMON_T_FAULT ), NULL @@ -575,6 +672,8 @@ static const struct i2c_device_id emc1403_idtable[] = { { "emc1422", emc1402 }, { "emc1423", emc1403 }, { "emc1424", emc1404 }, + { "emc1428", emc1428 }, + { "emc1438", emc1428 }, { "emc1442", emc1402 }, { } }; -- cgit v1.2.3 From 5fbf8734fb36cf67339f599f0e51747a6aff690c Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sun, 12 May 2024 09:07:01 -0700 Subject: hwmon: (nzxt-kraken3) Bail out for unsupported device variants Dan Carpenter reports: Commit cbeb479ff4cd ("hwmon: (nzxt-kraken3) Decouple device names from kinds") from Apr 28, 2024 (linux-next), leads to the following Smatch static checker warning: drivers/hwmon/nzxt-kraken3.c:957 kraken3_probe() error: uninitialized symbol 'device_name'. Indeed, 'device_name' will be uninitizalized if an unknown product is encountered. In practice this should not matter because the driver should not instantiate on unknown products, but lets play safe and bail out if that happens. Reported-by: Dan Carpenter Closes: https://lore.kernel.org/linux-hwmon/b1738c50-db42-40f0-a899-9c027c131ffb@moroto.mountain/ Cc: Jonas Malaco Cc: Aleksa Savic Fixes: cbeb479ff4cd ("hwmon: (nzxt-kraken3) Decouple device names from kinds") Acked-by: Jonas Malaco Signed-off-by: Guenter Roeck --- drivers/hwmon/nzxt-kraken3.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/nzxt-kraken3.c b/drivers/hwmon/nzxt-kraken3.c index 0b3f04c740b0..00f3ac90a290 100644 --- a/drivers/hwmon/nzxt-kraken3.c +++ b/drivers/hwmon/nzxt-kraken3.c @@ -928,7 +928,8 @@ static int kraken3_probe(struct hid_device *hdev, const struct hid_device_id *id device_name = "kraken2023elite"; break; default: - break; + ret = -ENODEV; + goto fail_and_close; } priv->buffer = devm_kzalloc(&hdev->dev, MAX_REPORT_LENGTH, GFP_KERNEL); -- cgit v1.2.3