mirror of
https://github.com/torvalds/linux
synced 2024-10-04 18:33:42 +00:00
hwmon updates for v6.10
* New drivers - Infineon XDP710 - EC Chip driver for Lenovo ThinkStation motherboards - Analog Devices ADP1050 * Improved support for existing drivers - emc1403: Convert to with_info API; Support for EMC1428 and EMC1438 - nzxt-kraken3: Support for NZXT Kraken 2023 - aquacomputer_d5next: Support for Octo flow sensors - pmbus/adm1275: Support for ADM1281 - dell-smm: Supportt for Precision 7540 and G5 5505 * Other notable cleanup - max6639: Use regmap - Remove unused structure fields from multiple drivers - Drop explicit initialization of struct i2c_device_id::driver_data to 0 - Improve configuration mode handling in it87 driver - jc42: Drop support for I2C_CLASS_SPD - Various conversions to devicetree schema - Add HAS_IOPORT dependencies as needed * Minor fixes and improvements to max31790, coretemp, aspeed-g6-pwm-tach, pwm-fan, pmbus/mp2975, acpi_power_meter, and lm70 drivers -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEiHPvMQj9QTOCiqgVyx8mb86fmYEFAmZCnOsACgkQyx8mb86f mYGGIg//Z/P2SNdU+WztPIpLLu19zGe0S0PskGmw/3Ox5Wu95hOyv2FkABkbLOnI a0Q69ntPjKtwhziVgws9hcqM33++yz4J8k7Y3UJ7yrGtua4OCLtlm4po9NxomxwR 5/iNBwDD2fWxOMTfAKCKanYLk+tgvB1xV0SfGN7jmTSL5GLwWZGtHYKzmgbNvdAN tAZGF9RlO4bj4eORFaGvbMyrLZuvT2zWzpcuqyvrZQZzcrFJzQgKqeGl6Jv+0Hsm LUOIlB8u82hTmyTsZ2PW9TI8sd7Q++3WilVvxB44cmridyst3Ucrcr1KlDBOu6oO gxCzHF/MAkQWa8UVmc3OAkfH9+VM3JxOfYNWHpcVNtEqucrJn+ryCrO33ZjUSjLK GdvLs0vFoImx1XSjVs8fUIVcsBs7FgkLuruxxJg7uElfYRGMyDzPaTMW//Iwqul6 RX8/8Td2kYPGdiRDymE/ONQ5LIzZtUvnQUJap5ehHuZmVEIeybBHRXAAn8iG4mUg fQAB1imybjsV1yfulfOcA3P+izh/2wpeVlrQDsbMdiUEhD7Xhsrr+GFfIPrvWuGd IDWjhu2YP6t9R6yeA9H2W9MhiGNTZmv6bZerhS5InoR93d92pxwkPehwdrwV+mC2 Ou9ULI9hmJPqEIdCENTCNj1TFUhEZtNhJxjLpaxoMYjx0FMU9aI= =68su -----END PGP SIGNATURE----- Merge tag 'hwmon-for-v6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging Pull hwmon updates from Guenter Roeck: "New drivers: - Infineon XDP710 - EC Chip driver for Lenovo ThinkStation motherboards - Analog Devices ADP1050 Improved support for existing drivers: - emc1403: Convert to with_info API; Support for EMC1428 and EMC1438 - nzxt-kraken3: Support for NZXT Kraken 2023 - aquacomputer_d5next: Support for Octo flow sensors - pmbus/adm1275: Support for ADM1281 - dell-smm: Supportt for Precision 7540 and G5 5505 Other notable cleanup: - max6639: Use regmap - Remove unused structure fields from multiple drivers - Drop explicit initialization of struct i2c_device_id::driver_data to zero - Improve configuration mode handling in it87 driver - jc42: Drop support for I2C_CLASS_SPD - Various conversions to devicetree schema - Add HAS_IOPORT dependencies as needed Minor fixes and improvements to max31790, coretemp, aspeed-g6-pwm-tach, pwm-fan, pmbus/mp2975, acpi_power_meter, and lm70 drivers" * tag 'hwmon-for-v6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (52 commits) hwmon: (nzxt-kraken3) Bail out for unsupported device variants hwmon: (emc1403) Add support for EMC1428 and EMC1438. hwmon: Drop explicit initialization of struct i2c_device_id::driver_data to 0 (part 2) hwmon: (emc1403) Add support for conversion interval configuration hwmon: (emc1403) Support 11 bit accuracy hwmon: (emc1403) Convert to with_info API hwmon: (max6639) Use regmap hwmon: (npcm750-pwm-fan) Remove another unused field in struct npcm7xx_cooling_device hwmon: (npcm750-pwm-fan) Remove an unused field in struct npcm7xx_cooling_device hwmon: (stts751) Remove an unused field in struct stts751_priv hwmon: Drop explicit initialization of struct i2c_device_id::driver_data to 0 hwmon: (max31790) revise the scale to write pwm hwmon: (nzxt-kraken3) Add support for NZXT Kraken 2023 (standard and Elite) models hwmon: (nzxt-kraken3) Decouple device names from kinds hwmon: (it87) Remove tests nolonger required hwmon: (it87) Test for chipset before entering configuration mode hwmon: (it87) Do not enter configuration mode for some chiptypes hwmon: (it87) Rename FEAT_CONF_NOEXIT to FEAT_NOCONF as more descriptive of requirement hwmon: (pmbus) Add support for Infineon XDP710 dt-bindings: hwmon: Add infineon xdp710 driver bindings ...
This commit is contained in:
commit
a8cc7eb996
|
@ -1,38 +0,0 @@
|
|||
TI ADC128D818 ADC System Monitor With Temperature Sensor
|
||||
--------------------------------------------------------
|
||||
|
||||
Operation modes:
|
||||
|
||||
- Mode 0: 7 single-ended voltage readings (IN0-IN6),
|
||||
1 temperature reading (internal)
|
||||
- Mode 1: 8 single-ended voltage readings (IN0-IN7),
|
||||
no temperature
|
||||
- Mode 2: 4 pseudo-differential voltage readings
|
||||
(IN0-IN1, IN3-IN2, IN4-IN5, IN7-IN6),
|
||||
1 temperature reading (internal)
|
||||
- Mode 3: 4 single-ended voltage readings (IN0-IN3),
|
||||
2 pseudo-differential voltage readings
|
||||
(IN4-IN5, IN7-IN6),
|
||||
1 temperature reading (internal)
|
||||
|
||||
If no operation mode is configured via device tree, the driver keeps the
|
||||
currently active chip operation mode (default is mode 0).
|
||||
|
||||
|
||||
Required node properties:
|
||||
|
||||
- compatible: must be set to "ti,adc128d818"
|
||||
- reg: I2C address of the device
|
||||
|
||||
Optional node properties:
|
||||
|
||||
- ti,mode: Operation mode (u8) (see above).
|
||||
|
||||
|
||||
Example (operation mode 2):
|
||||
|
||||
adc128d818@1d {
|
||||
compatible = "ti,adc128d818";
|
||||
reg = <0x1d>;
|
||||
ti,mode = /bits/ 8 <2>;
|
||||
};
|
|
@ -5,7 +5,7 @@
|
|||
$id: http://devicetree.org/schemas/hwmon/adi,adm1275.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Analog Devices ADM1075/ADM127x/ADM129x digital power monitors
|
||||
title: Analog Devices ADM1075/ADM127x/ADM1281/ADM129x digital power monitors
|
||||
|
||||
maintainers:
|
||||
- Krzysztof Kozlowski <krzk@kernel.org>
|
||||
|
@ -27,6 +27,7 @@ properties:
|
|||
- adi,adm1275
|
||||
- adi,adm1276
|
||||
- adi,adm1278
|
||||
- adi,adm1281
|
||||
- adi,adm1293
|
||||
- adi,adm1294
|
||||
|
||||
|
@ -91,6 +92,7 @@ allOf:
|
|||
contains:
|
||||
enum:
|
||||
- adi,adm1278
|
||||
- adi,adm1281
|
||||
- adi,adm1293
|
||||
- adi,adm1294
|
||||
then:
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
Bindings for Synaptics AS370 PVT sensors
|
||||
|
||||
Required properties:
|
||||
- compatible : "syna,as370-hwmon"
|
||||
- reg : address and length of the register set.
|
||||
|
||||
Example:
|
||||
hwmon@ea0810 {
|
||||
compatible = "syna,as370-hwmon";
|
||||
reg = <0xea0810 0xc>;
|
||||
};
|
37
Documentation/devicetree/bindings/hwmon/ibm,opal-sensor.yaml
Normal file
37
Documentation/devicetree/bindings/hwmon/ibm,opal-sensor.yaml
Normal file
|
@ -0,0 +1,37 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/hwmon/ibm,opal-sensor.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: IBM POWERNV platform sensors
|
||||
|
||||
maintainers:
|
||||
- Javier Carrasco <javier.carrasco.cruz@gmail.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- ibm,opal-sensor-cooling-fan
|
||||
- ibm,opal-sensor-amb-temp
|
||||
- ibm,opal-sensor-power-supply
|
||||
- ibm,opal-sensor-power
|
||||
|
||||
sensor-id:
|
||||
description:
|
||||
An opaque id provided by the firmware to the kernel, identifies a
|
||||
given sensor and its attribute data.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- sensor-id
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
sensor {
|
||||
compatible = "ibm,opal-sensor-cooling-fan";
|
||||
sensor-id = <0x7052107>;
|
||||
};
|
|
@ -1,25 +0,0 @@
|
|||
Device-tree bindings for I2C-based On-Chip Controller hwmon device
|
||||
------------------------------------------------------------------
|
||||
|
||||
Required properties:
|
||||
- compatible = "ibm,p8-occ-hwmon";
|
||||
- reg = <I2C address>; : I2C bus address
|
||||
|
||||
Examples:
|
||||
|
||||
i2c-bus@100 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clock-frequency = <100000>;
|
||||
< more properties >
|
||||
|
||||
occ-hwmon@1 {
|
||||
compatible = "ibm,p8-occ-hwmon";
|
||||
reg = <0x50>;
|
||||
};
|
||||
|
||||
occ-hwmon@2 {
|
||||
compatible = "ibm,p8-occ-hwmon";
|
||||
reg = <0x51>;
|
||||
};
|
||||
};
|
|
@ -1,23 +0,0 @@
|
|||
IBM POWERNV platform sensors
|
||||
----------------------------
|
||||
|
||||
Required node properties:
|
||||
- compatible: must be one of
|
||||
"ibm,opal-sensor-cooling-fan"
|
||||
"ibm,opal-sensor-amb-temp"
|
||||
"ibm,opal-sensor-power-supply"
|
||||
"ibm,opal-sensor-power"
|
||||
- sensor-id: an opaque id provided by the firmware to the kernel, identifies a
|
||||
given sensor and its attribute data
|
||||
|
||||
Example sensors node:
|
||||
|
||||
cooling-fan#8-data {
|
||||
sensor-id = <0x7052107>;
|
||||
compatible = "ibm,opal-sensor-cooling-fan";
|
||||
};
|
||||
|
||||
amb-temp#1-thrs {
|
||||
sensor-id = <0x5096000>;
|
||||
compatible = "ibm,opal-sensor-amb-temp";
|
||||
};
|
|
@ -1,30 +0,0 @@
|
|||
*LM87 hwmon sensor.
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be
|
||||
"ti,lm87"
|
||||
|
||||
- reg: I2C address
|
||||
|
||||
optional properties:
|
||||
- has-temp3: This configures pins 18 and 19 to be used as a second
|
||||
remote temperature sensing channel. By default the pins
|
||||
are configured as voltage input pins in0 and in5.
|
||||
|
||||
- has-in6: When set, pin 5 is configured to be used as voltage input
|
||||
in6. Otherwise the pin is set as FAN1 input.
|
||||
|
||||
- has-in7: When set, pin 6 is configured to be used as voltage input
|
||||
in7. Otherwise the pin is set as FAN2 input.
|
||||
|
||||
- vcc-supply: a Phandle for the regulator supplying power, can be
|
||||
configured to measure 5.0V power supply. Default is 3.3V.
|
||||
|
||||
Example:
|
||||
|
||||
lm87@2e {
|
||||
compatible = "ti,lm87";
|
||||
reg = <0x2e>;
|
||||
has-temp3;
|
||||
vcc-supply = <®_5v0>;
|
||||
};
|
|
@ -1,28 +0,0 @@
|
|||
Bindings for MAX6651 and MAX6650 I2C fan controllers
|
||||
|
||||
Reference:
|
||||
[1] https://datasheets.maximintegrated.com/en/ds/MAX6650-MAX6651.pdf
|
||||
|
||||
Required properties:
|
||||
- compatible : One of "maxim,max6650" or "maxim,max6651"
|
||||
- reg : I2C address, one of 0x1b, 0x1f, 0x4b, 0x48.
|
||||
|
||||
Optional properties, default is to retain the chip's current setting:
|
||||
- maxim,fan-microvolt : The supply voltage of the fan, either 5000000 uV or
|
||||
12000000 uV.
|
||||
- maxim,fan-prescale : Pre-scaling value, as per datasheet [1]. Lower values
|
||||
allow more fine-grained control of slower fans.
|
||||
Valid: 1, 2, 4, 8, 16.
|
||||
- maxim,fan-target-rpm: Initial requested fan rotation speed. If specified, the
|
||||
driver selects closed-loop mode and the requested speed.
|
||||
This ensures the fan is already running before userspace
|
||||
takes over.
|
||||
|
||||
Example:
|
||||
fan-max6650: max6650@1b {
|
||||
reg = <0x1b>;
|
||||
compatible = "maxim,max6650";
|
||||
maxim,fan-microvolt = <12000000>;
|
||||
maxim,fan-prescale = <4>;
|
||||
maxim,fan-target-rpm = <1200>;
|
||||
};
|
70
Documentation/devicetree/bindings/hwmon/maxim,max6650.yaml
Normal file
70
Documentation/devicetree/bindings/hwmon/maxim,max6650.yaml
Normal file
|
@ -0,0 +1,70 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
|
||||
$id: http://devicetree.org/schemas/hwmon/maxim,max6650.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Maxim MAX6650 and MAX6651 I2C Fan Controllers
|
||||
|
||||
maintainers:
|
||||
- Javier Carrasco <javier.carrasco.cruz@gmail.com>
|
||||
|
||||
description: |
|
||||
The MAX6650 and MAX6651 regulate and monitor the speed
|
||||
of 5VDC/12VDC burshless fans with built-in tachometers.
|
||||
|
||||
Datasheets:
|
||||
https://datasheets.maximintegrated.com/en/ds/MAX6650-MAX6651.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- maxim,max6650
|
||||
- maxim,max6651
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
maxim,fan-microvolt:
|
||||
description:
|
||||
The supply voltage of the fan, either 5000000 uV or
|
||||
12000000 uV.
|
||||
enum: [5000000, 12000000]
|
||||
|
||||
maxim,fan-prescale:
|
||||
description:
|
||||
Pre-scaling value, as per datasheet. Lower values
|
||||
allow more fine-grained control of slower fans.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [1, 2, 4, 8, 16]
|
||||
|
||||
maxim,fan-target-rpm:
|
||||
description:
|
||||
Initial requested fan rotation speed. If specified, the
|
||||
driver selects closed-loop mode and the requested speed.
|
||||
This ensures the fan is already running before userspace
|
||||
takes over.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
maximum: 30000
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
fan-controller@1b {
|
||||
compatible = "maxim,max6650";
|
||||
reg = <0x1b>;
|
||||
maxim,fan-microvolt = <12000000>;
|
||||
maxim,fan-prescale = <4>;
|
||||
maxim,fan-target-rpm = <1200>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,49 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/hwmon/pmbus/adi,adp1050.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Analog Devices ADP1050 digital controller with PMBus interface
|
||||
|
||||
maintainers:
|
||||
- Radu Sabau <radu.sabau@analog.com>
|
||||
|
||||
description: |
|
||||
The ADP1050 is used to monitor system voltages, currents and temperatures.
|
||||
Through the PMBus interface, the ADP1050 targets isolated power supplies
|
||||
and has four individual monitors for input/output voltage, input current
|
||||
and temperature.
|
||||
Datasheet:
|
||||
https://www.analog.com/en/products/adp1050.html
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: adi,adp1050
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vcc-supply: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vcc-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clock-frequency = <100000>;
|
||||
|
||||
hwmon@70 {
|
||||
compatible = "adi,adp1050";
|
||||
reg = <0x70>;
|
||||
vcc-supply = <&vcc>;
|
||||
};
|
||||
};
|
||||
...
|
|
@ -1 +0,0 @@
|
|||
This file has moved to pwm-fan.yaml.
|
41
Documentation/devicetree/bindings/hwmon/st,stts751.yaml
Normal file
41
Documentation/devicetree/bindings/hwmon/st,stts751.yaml
Normal file
|
@ -0,0 +1,41 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/hwmon/st,stts751.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: STTS751 Thermometer
|
||||
|
||||
maintainers:
|
||||
- Javier Carrasco <javier.carrasco.cruz@gmail.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: st,stts751
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
smbus-timeout-disable:
|
||||
description:
|
||||
When set, the smbus timeout function will be disabled.
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
thermometer@48 {
|
||||
compatible = "st,stts751";
|
||||
reg = <0x48>;
|
||||
smbus-timeout-disable;
|
||||
};
|
||||
};
|
|
@ -1,15 +0,0 @@
|
|||
* STTS751 thermometer.
|
||||
|
||||
Required node properties:
|
||||
- compatible: "stts751"
|
||||
- reg: I2C bus address of the device
|
||||
|
||||
Optional properties:
|
||||
- smbus-timeout-disable: when set, the smbus timeout function will be disabled
|
||||
|
||||
Example stts751 node:
|
||||
|
||||
temp-sensor {
|
||||
compatible = "stts751";
|
||||
reg = <0x48>;
|
||||
}
|
32
Documentation/devicetree/bindings/hwmon/syna,as370.yaml
Normal file
32
Documentation/devicetree/bindings/hwmon/syna,as370.yaml
Normal file
|
@ -0,0 +1,32 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/hwmon/syna,as370.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Synaptics AS370 PVT sensors
|
||||
|
||||
maintainers:
|
||||
- Javier Carrasco <javier.carrasco.cruz@gmail.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: syna,as370-hwmon
|
||||
|
||||
reg:
|
||||
description:
|
||||
Address and length of the register set.
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
sensor@ea0810 {
|
||||
compatible = "syna,as370-hwmon";
|
||||
reg = <0xea0810 0xc>;
|
||||
};
|
63
Documentation/devicetree/bindings/hwmon/ti,adc128d818.yaml
Normal file
63
Documentation/devicetree/bindings/hwmon/ti,adc128d818.yaml
Normal file
|
@ -0,0 +1,63 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
|
||||
$id: http://devicetree.org/schemas/hwmon/ti,adc128d818.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Texas Instruments ADC128D818 ADC System Monitor With Temperature Sensor
|
||||
|
||||
maintainers:
|
||||
- Javier Carrasco <javier.carrasco.cruz@gmail.com>
|
||||
|
||||
description: |
|
||||
The ADC128D818 is a 12-Bit, 8-Channel Analog to Digital Converter (ADC)
|
||||
with a temperature sensor and an I2C interface.
|
||||
|
||||
Datasheets:
|
||||
https://www.ti.com/product/ADC128D818
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: ti,adc128d818
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
ti,mode:
|
||||
$ref: /schemas/types.yaml#/definitions/uint8
|
||||
description: |
|
||||
Operation mode.
|
||||
Mode 0 - 7 single-ended voltage readings (IN0-IN6), 1 temperature
|
||||
reading (internal).
|
||||
Mode 1 - 8 single-ended voltage readings (IN0-IN7), no temperature.
|
||||
Mode 2 - 4 pseudo-differential voltage readings
|
||||
(IN0-IN1, IN3-IN2, IN4-IN5, IN7-IN6), 1 temperature reading (internal).
|
||||
Mode 3 - 4 single-ended voltage readings (IN0-IN3), 2 pseudo-differential
|
||||
voltage readings (IN4-IN5, IN7-IN6), 1 temperature reading (internal).
|
||||
default: 0
|
||||
|
||||
vref-supply:
|
||||
description:
|
||||
The regulator to use as an external reference. If it does not exist, the
|
||||
internal reference will be used.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
adc@1d {
|
||||
compatible = "ti,adc128d818";
|
||||
reg = <0x1d>;
|
||||
vref-supply = <&vref>;
|
||||
ti,mode = /bits/ 8 <2>;
|
||||
};
|
||||
};
|
69
Documentation/devicetree/bindings/hwmon/ti,lm87.yaml
Normal file
69
Documentation/devicetree/bindings/hwmon/ti,lm87.yaml
Normal file
|
@ -0,0 +1,69 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
|
||||
$id: http://devicetree.org/schemas/hwmon/ti,lm87.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Texas Instruments LM87 Hardware Monitor
|
||||
|
||||
maintainers:
|
||||
- Javier Carrasco <javier.carrasco.cruz@gmail.com>
|
||||
|
||||
description: |
|
||||
The LM87 is a serial interface system hardware monitor
|
||||
with remote diode temperature sensing.
|
||||
|
||||
Datasheets:
|
||||
https://www.ti.com/product/LM87
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: ti,lm87
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
has-temp3:
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
description:
|
||||
This configures pins 18 and 19 to be used as a second
|
||||
remote temperature sensing channel. By default the pins
|
||||
are configured as voltage input pins in0 and in5.
|
||||
|
||||
has-in6:
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
description:
|
||||
When set, pin 5 is configured to be used as voltage input
|
||||
in6. Otherwise the pin is set as FAN1 input.
|
||||
|
||||
has-in7:
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
description:
|
||||
When set, pin 6 is configured to be used as voltage input
|
||||
in7. Otherwise the pin is set as FAN2 input.
|
||||
|
||||
vcc-supply:
|
||||
description:
|
||||
Regulator supplying power, can be configured to measure
|
||||
5.0V power supply. Default is 3.3V.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
hwmon@2e {
|
||||
compatible = "ti,lm87";
|
||||
reg = <0x2e>;
|
||||
has-temp3;
|
||||
vcc-supply = <®_5v0>;
|
||||
};
|
||||
};
|
|
@ -126,6 +126,8 @@ properties:
|
|||
- ibm,cffps1
|
||||
# IBM Common Form Factor Power Supply Versions 2
|
||||
- ibm,cffps2
|
||||
# IBM On-Chip Controller hwmon device
|
||||
- ibm,p8-occ-hwmon
|
||||
# Infineon barometric pressure and temperature sensor
|
||||
- infineon,dps310
|
||||
# Infineon IR36021 digital POL buck controller
|
||||
|
@ -134,6 +136,8 @@ properties:
|
|||
- infineon,irps5401
|
||||
# Infineon TLV493D-A1B6 I2C 3D Magnetic Sensor
|
||||
- infineon,tlv493d-a1b6
|
||||
# Infineon Hot-swap controller xdp710
|
||||
- infineon,xdp710
|
||||
# Infineon Multi-phase Digital VR Controller xdpe11280
|
||||
- infineon,xdpe11280
|
||||
# Infineon Multi-phase Digital VR Controller xdpe12254
|
||||
|
|
|
@ -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.
|
||||
======================= =======================================================
|
||||
|
|
64
Documentation/hwmon/adp1050.rst
Normal file
64
Documentation/hwmon/adp1050.rst
Normal file
|
@ -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 <radu.sabau@analog.com>
|
||||
|
||||
|
||||
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
|
||||
================= ========================================
|
|
@ -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. 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,
|
||||
|
@ -95,11 +95,12 @@ 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)
|
||||
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)
|
||||
|
|
|
@ -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 <kalhan.trisal@intel.com
|
||||
|
||||
|
@ -53,10 +64,10 @@ Description
|
|||
-----------
|
||||
|
||||
The Standard Microsystems Corporation (SMSC) / Microchip EMC14xx chips
|
||||
contain up to four temperature sensors. EMC14x2 support two sensors
|
||||
contain up to eight temperature sensors. EMC14x2 support two sensors
|
||||
(one internal, one external). EMC14x3 support three sensors (one internal,
|
||||
two external), and EMC14x4 support four sensors (one internal, three
|
||||
external).
|
||||
two external), EMC14x4 support four sensors (one internal, three external),
|
||||
and EMC14x8 support eight sensors (one internal, seven external).
|
||||
|
||||
The chips implement three limits for each sensor: low (tempX_min), high
|
||||
(tempX_max) and critical (tempX_crit.) The chips also implement an
|
||||
|
|
|
@ -33,6 +33,7 @@ Hardware Monitoring Kernel Drivers
|
|||
adm1266
|
||||
adm1275
|
||||
adm9240
|
||||
adp1050
|
||||
ads7828
|
||||
adt7410
|
||||
adt7411
|
||||
|
@ -250,6 +251,7 @@ Hardware Monitoring Kernel Drivers
|
|||
wm831x
|
||||
wm8350
|
||||
xgene-hwmon
|
||||
xdp710
|
||||
xdpe12284
|
||||
xdpe152c4
|
||||
zl6100
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -152,7 +152,7 @@ Emerson DS1200 power modules might look as follows::
|
|||
}
|
||||
|
||||
static const struct i2c_device_id ds1200_id[] = {
|
||||
{"ds1200", 0},
|
||||
{"ds1200"},
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
83
Documentation/hwmon/xdp710.rst
Normal file
83
Documentation/hwmon/xdp710.rst
Normal file
|
@ -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 <peteryin.openbmc@gmail.com>
|
||||
|
||||
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**
|
|
@ -479,6 +479,13 @@ L: linux-wireless@vger.kernel.org
|
|||
S: Orphan
|
||||
F: drivers/net/wireless/admtek/adm8211.*
|
||||
|
||||
ADP1050 HARDWARE MONITOR DRIVER
|
||||
M: Radu Sabau <radu.sabau@analog.com>
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Supported
|
||||
W: https://ez.analog.com/linux-software-drivers
|
||||
F: Documentation/devicetree/bindings/hwmon/pmbus/adi,adp1050.yaml
|
||||
|
||||
ADP1653 FLASH CONTROLLER DRIVER
|
||||
M: Sakari Ailus <sakari.ailus@iki.fi>
|
||||
L: linux-media@vger.kernel.org
|
||||
|
|
|
@ -22,6 +22,8 @@ MODULE_LICENSE("GPL");
|
|||
/* the IPMI timeout is 5s */
|
||||
#define IPMI_TIMEOUT (5000)
|
||||
#define ACPI_IPMI_MAX_MSG_LENGTH 64
|
||||
/* 2s should be suffient for SMI being selected */
|
||||
#define ACPI_IPMI_SMI_SELECTION_TIMEOUT (2 * HZ)
|
||||
|
||||
struct acpi_ipmi_device {
|
||||
/* the device list attached to driver_data.ipmi_devices */
|
||||
|
@ -54,6 +56,7 @@ struct ipmi_driver_data {
|
|||
* to this selected global IPMI system interface.
|
||||
*/
|
||||
struct acpi_ipmi_device *selected_smi;
|
||||
struct completion smi_selection_done;
|
||||
};
|
||||
|
||||
struct acpi_ipmi_msg {
|
||||
|
@ -463,8 +466,10 @@ static void ipmi_register_bmc(int iface, struct device *dev)
|
|||
if (temp->handle == handle)
|
||||
goto err_lock;
|
||||
}
|
||||
if (!driver_data.selected_smi)
|
||||
if (!driver_data.selected_smi) {
|
||||
driver_data.selected_smi = ipmi_device;
|
||||
complete(&driver_data.smi_selection_done);
|
||||
}
|
||||
list_add_tail(&ipmi_device->head, &driver_data.ipmi_devices);
|
||||
mutex_unlock(&driver_data.ipmi_lock);
|
||||
|
||||
|
@ -578,6 +583,20 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address,
|
|||
return status;
|
||||
}
|
||||
|
||||
int acpi_wait_for_acpi_ipmi(void)
|
||||
{
|
||||
long ret;
|
||||
|
||||
ret = wait_for_completion_interruptible_timeout(&driver_data.smi_selection_done,
|
||||
ACPI_IPMI_SMI_SELECTION_TIMEOUT);
|
||||
|
||||
if (ret <= 0)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_wait_for_acpi_ipmi);
|
||||
|
||||
static int __init acpi_ipmi_init(void)
|
||||
{
|
||||
int result;
|
||||
|
@ -586,6 +605,8 @@ static int __init acpi_ipmi_init(void)
|
|||
if (acpi_disabled)
|
||||
return 0;
|
||||
|
||||
init_completion(&driver_data.smi_selection_done);
|
||||
|
||||
status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
|
||||
ACPI_ADR_SPACE_IPMI,
|
||||
&acpi_ipmi_space_handler,
|
||||
|
|
|
@ -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
|
||||
|
@ -914,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
|
||||
|
@ -1220,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.
|
||||
|
@ -1561,6 +1575,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 +1590,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 +1622,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 +1644,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
|
||||
|
@ -1778,7 +1796,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.
|
||||
|
@ -1883,7 +1901,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 +1921,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 +1978,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 +2013,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 +2028,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 +2042,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 +2295,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 +2305,7 @@ config SENSORS_VIA686A
|
|||
|
||||
config SENSORS_VT1211
|
||||
tristate "VIA VT1211"
|
||||
depends on HAS_IOPORT
|
||||
depends on !PPC
|
||||
select HWMON_VID
|
||||
help
|
||||
|
@ -2293,7 +2317,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 +2425,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 +2438,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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -480,7 +480,7 @@ static int adc128_probe(struct i2c_client *client)
|
|||
}
|
||||
|
||||
static const struct i2c_device_id adc128_id[] = {
|
||||
{ "adc128d818", 0 },
|
||||
{ "adc128d818" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, adc128_id);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -202,16 +202,19 @@ 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 */
|
||||
#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 };
|
||||
|
||||
|
@ -363,18 +366,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 +399,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 +848,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 */
|
||||
|
@ -857,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:
|
||||
|
@ -1289,7 +1301,8 @@ 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_F_INPUT | HWMON_F_LABEL | HWMON_F_PULSES),
|
||||
HWMON_CHANNEL_INFO(power,
|
||||
HWMON_P_INPUT | HWMON_P_LABEL,
|
||||
HWMON_P_INPUT | HWMON_P_LABEL,
|
||||
|
@ -1658,16 +1671,20 @@ 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;
|
||||
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;
|
||||
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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 = {
|
||||
|
@ -1506,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 = {
|
||||
|
|
|
@ -233,7 +233,7 @@ static int ds620_probe(struct i2c_client *client)
|
|||
}
|
||||
|
||||
static const struct i2c_device_id ds620_id[] = {
|
||||
{"ds620", 0},
|
||||
{"ds620"},
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -19,302 +19,56 @@
|
|||
#include <linux/sysfs.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/util_macros.h>
|
||||
|
||||
#define THERMAL_PID_REG 0xfd
|
||||
#define THERMAL_SMSC_ID_REG 0xfe
|
||||
#define THERMAL_REVISION_REG 0xff
|
||||
|
||||
enum emc1403_chip { emc1402, emc1403, emc1404 };
|
||||
enum emc1403_chip { emc1402, emc1403, emc1404, emc1428 };
|
||||
|
||||
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));
|
||||
|
||||
retval = regmap_update_bits(data->regmap, 0x03, BIT(6),
|
||||
val ? BIT(6) : 0);
|
||||
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;
|
||||
|
||||
if (kstrtoul(buf, 10, &val))
|
||||
return -EINVAL;
|
||||
|
||||
retval = regmap_update_bits(data->regmap, sda->nr, sda->index,
|
||||
val ? sda->index : 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,
|
||||
&dev_attr_power_state.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,
|
||||
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)
|
||||
|
@ -346,6 +100,12 @@ static int emc1403_detect(struct i2c_client *client,
|
|||
case 0x27:
|
||||
strscpy(info->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;
|
||||
|
@ -376,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;
|
||||
|
@ -389,51 +157,508 @@ 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,
|
||||
},
|
||||
[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] = {
|
||||
[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,
|
||||
},
|
||||
[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)
|
||||
{
|
||||
struct thermal_data *data;
|
||||
struct device *hwmon_dev;
|
||||
const struct i2c_device_id *id = i2c_match_id(emc1403_idtable, client);
|
||||
unsigned int regvalh;
|
||||
unsigned int regvall = 0;
|
||||
int ret;
|
||||
s8 reg;
|
||||
|
||||
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], ®valh);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
data->regmap = devm_regmap_init_i2c(client, &emc1403_regmap_config);
|
||||
if (IS_ERR(data->regmap))
|
||||
return PTR_ERR(data->regmap);
|
||||
|
||||
mutex_init(&data->mutex);
|
||||
|
||||
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;
|
||||
reg = emc1403_temp_regs_low[channel][map];
|
||||
if (reg >= 0) {
|
||||
ret = regmap_read(data->regmap, reg, ®vall);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (id->driver_data == emc1402)
|
||||
data->groups[1] = &emc1402_alarm_group;
|
||||
if (data->chip == emc1428)
|
||||
*val = sign_extend32((regvalh << 3) | (regvall >> 5), 10) * 125;
|
||||
else
|
||||
*val = ((regvalh << 3) | (regvall >> 5)) * 125;
|
||||
|
||||
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);
|
||||
|
||||
dev_info(&client->dev, "%s Thermal chip found\n", id->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const unsigned short emc1403_address_list[] = {
|
||||
0x18, 0x1c, 0x29, 0x3c, 0x4c, 0x4d, 0x5c, I2C_CLIENT_END
|
||||
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_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)
|
||||
{
|
||||
struct thermal_data *data = dev_get_drvdata(dev);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
static int emc1403_set_hyst(struct thermal_data *data, long val)
|
||||
{
|
||||
int hyst, ret;
|
||||
long limit;
|
||||
|
||||
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);
|
||||
if (ret < 0)
|
||||
goto unlock;
|
||||
|
||||
hyst = limit - val;
|
||||
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);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int emc1403_set_temp(struct thermal_data *data, int channel,
|
||||
enum emc1403_reg_map map, long val)
|
||||
{
|
||||
unsigned int regval;
|
||||
int ret;
|
||||
u8 regh;
|
||||
s8 regl;
|
||||
|
||||
regh = emc1403_temp_regs[channel][map];
|
||||
regl = emc1403_temp_regs_low[channel][map];
|
||||
|
||||
mutex_lock(&data->mutex);
|
||||
if (regl >= 0) {
|
||||
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) & 0xff);
|
||||
if (ret < 0)
|
||||
goto unlock;
|
||||
ret = regmap_write(data->regmap, regl, (regval & 0x07) << 5);
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
unlock:
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
struct thermal_data *data = dev_get_drvdata(dev);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
if (data->chip != emc1428 && channel > 3)
|
||||
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_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 |
|
||||
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,
|
||||
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
|
||||
};
|
||||
|
||||
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 */
|
||||
|
@ -447,11 +672,42 @@ static const struct i2c_device_id emc1403_idtable[] = {
|
|||
{ "emc1422", emc1402 },
|
||||
{ "emc1423", emc1403 },
|
||||
{ "emc1424", emc1404 },
|
||||
{ "emc1428", emc1428 },
|
||||
{ "emc1438", emc1428 },
|
||||
{ "emc1442", emc1402 },
|
||||
{ }
|
||||
};
|
||||
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 = {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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" },
|
||||
{ },
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -320,7 +321,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 +453,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 +462,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 +508,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 +545,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)
|
||||
|
@ -742,13 +743,13 @@ 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);
|
||||
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;
|
||||
}
|
||||
|
@ -758,14 +759,14 @@ 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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -2666,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)
|
||||
|
@ -2673,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);
|
||||
/* 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 */
|
||||
|
@ -2766,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",
|
||||
|
@ -3143,7 +3186,7 @@ static int __init it87_find(int sioaddr, unsigned short *address,
|
|||
}
|
||||
|
||||
exit:
|
||||
superio_exit(sioaddr, config ? has_conf_noexit(config) : false);
|
||||
superio_exit(sioaddr, !enabled);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -3520,7 +3563,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)",
|
||||
|
@ -3540,7 +3583,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)
|
||||
|
@ -3640,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
|
||||
|
@ -3683,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),
|
||||
{ }
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
@ -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,
|
||||
|
|
602
drivers/hwmon/lenovo-ec-sensors.c
Normal file
602
drivers/hwmon/lenovo-ec-sensors.c
Normal file
|
@ -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) <dober@lenovo.com>
|
||||
*
|
||||
* 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 <linux/acpi.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/units.h>
|
||||
|
||||
#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 <dober@lenovo.com>");
|
||||
MODULE_DESCRIPTION("HWMON driver for sensors accessible via EC in LENOVO motherboards");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -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);
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
* Copyright (C) 2006 Kaiwan N Billimoria <kaiwan@designergraphix.com>
|
||||
*
|
||||
* 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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -975,8 +975,8 @@ static int lm87_probe(struct i2c_client *client)
|
|||
*/
|
||||
|
||||
static const struct i2c_device_id lm87_id[] = {
|
||||
{ "lm87", 0 },
|
||||
{ "adm1024", 0 },
|
||||
{ "lm87" },
|
||||
{ "adm1024" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, lm87_id);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -457,8 +457,8 @@ static int lm95241_probe(struct i2c_client *client)
|
|||
|
||||
/* Driver data (common to all clients) */
|
||||
static const struct i2c_device_id lm95241_id[] = {
|
||||
{ "lm95231", 0 },
|
||||
{ "lm95241", 0 },
|
||||
{ "lm95231" },
|
||||
{ "lm95241" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, lm95241_id);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -508,7 +508,7 @@ static int ltc2945_probe(struct i2c_client *client)
|
|||
}
|
||||
|
||||
static const struct i2c_device_id ltc2945_id[] = {
|
||||
{"ltc2945", 0},
|
||||
{"ltc2945"},
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -200,7 +200,7 @@ static int ltc4222_probe(struct i2c_client *client)
|
|||
}
|
||||
|
||||
static const struct i2c_device_id ltc4222_id[] = {
|
||||
{"ltc4222", 0},
|
||||
{"ltc4222"},
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -163,7 +163,7 @@ static int ltc4260_probe(struct i2c_client *client)
|
|||
}
|
||||
|
||||
static const struct i2c_device_id ltc4260_id[] = {
|
||||
{"ltc4260", 0},
|
||||
{"ltc4260"},
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -222,7 +222,7 @@ static int ltc4261_probe(struct i2c_client *client)
|
|||
}
|
||||
|
||||
static const struct i2c_device_id ltc4261_id[] = {
|
||||
{"ltc4261", 0},
|
||||
{"ltc4261"},
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
|
@ -537,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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/platform_data/max6639.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
/* 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;
|
||||
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
/*
|
||||
* 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;
|
||||
|
||||
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;
|
||||
|
||||
return sprintf(buf, "%d\n", (data->temp_alert[attr->index] * 1000));
|
||||
res = regmap_read(data->regmap, MAX6639_REG_ALERT_LIMIT(attr->index), &val);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
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;
|
||||
|
||||
return sprintf(buf, "%d\n", (data->temp_ot[attr->index] * 1000));
|
||||
res = regmap_read(data->regmap, MAX6639_REG_OT_LIMIT(attr->index), &val);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
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,16 +564,12 @@ 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[] = {
|
||||
{"max6639", 0},
|
||||
{"max6639"},
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -196,8 +196,6 @@ struct npcm7xx_pwm_fan_data {
|
|||
void __iomem *pwm_base;
|
||||
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];
|
||||
|
@ -692,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 */
|
||||
|
|
|
@ -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 <jonas@protocubo.io>
|
||||
* Copyright 2022 Aleksa Savic <savicaleksa83@gmail.com>
|
||||
|
@ -23,15 +23,12 @@
|
|||
#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;
|
||||
|
||||
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
|
||||
|
@ -141,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;
|
||||
|
@ -160,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;
|
||||
|
@ -247,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);
|
||||
|
@ -360,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);
|
||||
|
||||
|
@ -507,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;
|
||||
|
@ -774,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]);
|
||||
|
@ -849,14 +856,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 +873,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,12 +913,23 @@ 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;
|
||||
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;
|
||||
ret = -ENODEV;
|
||||
goto fail_and_close;
|
||||
}
|
||||
|
||||
priv->buffer = devm_kzalloc(&hdev->dev, MAX_REPORT_LENGTH, GFP_KERNEL);
|
||||
|
@ -936,8 +955,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 +963,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;
|
||||
|
||||
|
@ -972,6 +990,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) },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -51,12 +51,22 @@ 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.
|
||||
|
||||
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
|
||||
|
@ -511,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
|
||||
|
|
|
@ -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
|
||||
|
@ -51,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
|
||||
|
|
|
@ -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);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue