hwmon updates for v5.16-rc1
New drivers: - Maxim MAX6620 Notable functional enhancements: - Add Asus WMI support to nct6775 driver, and list boards supporting it - Move TMP461 support from tm401 driver to lm90 driver - Add support for fanX_min, fanX_max and fanX_target to dell-smm driver, and clean it up while doing so - Extend mlxreg-fan driver to support multiple cooling devices and multiple PWM channels. Also increase number of supported fan tachometers. - Add a new customer ID (for ASRock) to nct6683 driver - Make temperature/voltage sensors on nct7802 configurable - Add mfg_id debugfs entry to pmbus/ibm-cffps driver - Support configurable sense resistor values in pmbus/lm25066, and fix various coefficients - Use generic notification mechanism in raspberrypi driver Notable cleanup: - Convert various devicetree bindings to dtschema, and add missing bindings - Convert i5500_temp and tmp103 drivers to devm_hwmon_device_register_with_info - Clean up non-bool "valid" data fields - Improve devicetree configurability for tmp421 driver -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEiHPvMQj9QTOCiqgVyx8mb86fmYEFAmGACskACgkQyx8mb86f mYGZxw//XHZhm/cJEPlL9Rw8HmDWV49QwknswQ5kmSJWPOO1XziB2r3WUNqCKK/5 CVn/nvurp3MOdCjczywjYB1kz8FKXYW4savzkUbLypAGtYzMFaDRHFmyNj+t+Yw8 0WwdvBufuxgj8iHoGlc+HsiO8lhzdTrj1DM5Bv9ulwTNKvSeYBH4uceME9hlDcdv W47RU0sM16gPE3yojn0f5qhQEjzWlcax3u7FWOC0Oy9rZSJsngTLeaFOnoBB1EAn Va79etOq2MG8oGeYQZGRRjvLQQqmUg+db8rN1acXkpQ2LldiWaMy2frzGeY6BpH0 vYf00ScQieHgYn+HKQyYJPI2h0l/KyA4oCOr3KAoQwlwnNQBxJvX8jguvzTkwKmW RZySZuBNzP+RVWVD1bkkoEjmy8cjCjwKumHkF+Av3QSu743asjzKhNWdcSi1ZktD AE+3ihB/QFPVAx/XUHPk97EzkKeOUOsr9qcxwxMOakFMLbgi/y5jdPKWMIn4MFcT dn9lmLFM3fFwp/coSrAU2VWvw7lV3mkAb+qQ9l6bf5R28p42Vy+vw1ECPDc+TUL2 i1P+PR55nr48TqzEwgUFBtRnO+emye6bmJ1SVgrncwejrMoOc7OAPtF9LBoqC9ro rZvIw6a9VTOJYIE4jgfWuX/xgJd9w43rWwHr2CoCbHZ0BumS9/M= =v5CO -----END PGP SIGNATURE----- Merge tag 'hwmon-for-v5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging Pull hwmon updates from Guenter Roeck: "New driver: - Maxim MAX6620 Notable functional enhancements: - Add Asus WMI support to nct6775 driver, and list boards supporting it - Move TMP461 support from tm401 driver to lm90 driver - Add support for fanX_min, fanX_max and fanX_target to dell-smm driver, and clean it up while doing so - Extend mlxreg-fan driver to support multiple cooling devices and multiple PWM channels. Also increase number of supported fan tachometers. - Add a new customer ID (for ASRock) to nct6683 driver - Make temperature/voltage sensors on nct7802 configurable - Add mfg_id debugfs entry to pmbus/ibm-cffps driver - Support configurable sense resistor values in pmbus/lm25066, and fix various coefficients - Use generic notification mechanism in raspberrypi driver Notable cleanups: - Convert various devicetree bindings to dtschema, and add missing bindings - Convert i5500_temp and tmp103 drivers to devm_hwmon_device_register_with_info - Clean up non-bool "valid" data fields - Improve devicetree configurability for tmp421 driver" * tag 'hwmon-for-v5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (73 commits) hwmon: (nct7802) Add of_node_put() before return hwmon: (tmp401) Drop support for TMP461 hwmon: (lm90) Add basic support for TI TMP461 hwmon: (lm90) Introduce flag indicating extended temperature support hwmon: (nct6775) add ProArt X570-CREATOR WIFI. hwmon: (nct7802) Make temperature/voltage sensors configurable dt-bindings: hwmon: Add nct7802 bindings hwmon: (dell-smm) Speed up setting of fan speed hwmon: (dell-smm) Add comment explaining usage of i8k_config_data[] hwmon: (dell-smm) Return -ENOIOCTLCMD instead of -EINVAL hwmon: (dell-smm) Use strscpy_pad() hwmon: (dell-smm) Sort includes in alphabetical order hwmon: (tmp421) Add of_node_put() before return hwmon: (max31722) Warn about failure to put device in stand-by in .remove() hwmon: (acpi_power_meter) Use acpi_bus_get_acpi_device() hwmon: (dell-smm) Add support for fanX_min, fanX_max and fanX_target dt-bindings: hwmon: allow specifying channels for tmp421 hwmon: (tmp421) ignore non-channel related DT nodes hwmon: (tmp421) update documentation hwmon: (tmp421) support HWMON_T_ENABLE ...
This commit is contained in:
commit
d54f486035
|
@ -1,11 +0,0 @@
|
|||
Bindings for Delta Electronics DPS-650-AB power supply
|
||||
|
||||
Required properties:
|
||||
- compatible : "delta,dps650ab"
|
||||
- reg : I2C address, one of 0x58, 0x59.
|
||||
|
||||
Example:
|
||||
dps650ab@58 {
|
||||
compatible = "delta,dps650ab";
|
||||
reg = <0x58>;
|
||||
};
|
|
@ -1,12 +0,0 @@
|
|||
Honeywell Humidicon HIH-6130 humidity/temperature sensor
|
||||
--------------------------------------------------------
|
||||
|
||||
Requires node properties:
|
||||
- compatible : "honeywell,hi6130"
|
||||
- reg : the I2C address of the device. This is 0x27.
|
||||
|
||||
Example:
|
||||
hih6130@27 {
|
||||
compatible = "honeywell,hih6130";
|
||||
reg = <0x27>;
|
||||
};
|
|
@ -1,26 +0,0 @@
|
|||
Device-tree bindings for IBM Common Form Factor Power Supply Versions 1 and 2
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
Required properties:
|
||||
- compatible : Must be one of the following:
|
||||
"ibm,cffps1"
|
||||
"ibm,cffps2"
|
||||
or "ibm,cffps" if the system
|
||||
must support any version of the
|
||||
power supply
|
||||
- reg = < I2C bus address >; : Address of the power supply on the
|
||||
I2C bus.
|
||||
|
||||
Example:
|
||||
|
||||
i2c-bus@100 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
< more properties >
|
||||
|
||||
power-supply@68 {
|
||||
compatible = "ibm,cffps1";
|
||||
reg = <0x68>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,37 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/hwmon/iio-hwmon.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: ADC-attached Hardware Sensor Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- Jonathan Cameron <jic23@kernel.org>
|
||||
|
||||
description: >
|
||||
Bindings for hardware monitoring devices connected to ADC controllers
|
||||
supporting the Industrial I/O bindings.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: iio-hwmon
|
||||
|
||||
io-channels:
|
||||
minItems: 1
|
||||
maxItems: 8 # Should be enough
|
||||
description: >
|
||||
List of phandles to ADC channels to read the monitoring values
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- io-channels
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
iio-hwmon {
|
||||
compatible = "iio-hwmon";
|
||||
io-channels = <&adc 1>, <&adc 2>;
|
||||
};
|
|
@ -1,46 +0,0 @@
|
|||
Properties for Jedec JC-42.4 compatible temperature sensors
|
||||
|
||||
Required properties:
|
||||
- compatible: May include a device-specific string consisting of the
|
||||
manufacturer and the name of the chip. A list of supported
|
||||
chip names follows.
|
||||
Must include "jedec,jc-42.4-temp" for any Jedec JC-42.4
|
||||
compatible temperature sensor.
|
||||
|
||||
Supported chip names:
|
||||
adi,adt7408
|
||||
atmel,at30ts00
|
||||
atmel,at30tse004
|
||||
onnn,cat6095
|
||||
onnn,cat34ts02
|
||||
maxim,max6604
|
||||
microchip,mcp9804
|
||||
microchip,mcp9805
|
||||
microchip,mcp9808
|
||||
microchip,mcp98243
|
||||
microchip,mcp98244
|
||||
microchip,mcp9843
|
||||
nxp,se97
|
||||
nxp,se98
|
||||
st,stts2002
|
||||
st,stts2004
|
||||
st,stts3000
|
||||
st,stts424
|
||||
st,stts424e
|
||||
idt,tse2002
|
||||
idt,tse2004
|
||||
idt,ts3000
|
||||
idt,ts3001
|
||||
|
||||
- reg: I2C address
|
||||
|
||||
Optional properties:
|
||||
- smbus-timeout-disable: When set, the smbus timeout function will be disabled.
|
||||
This is not supported on all chips.
|
||||
|
||||
Example:
|
||||
|
||||
temp-sensor@1a {
|
||||
compatible = "jedec,jc-42.4-temp";
|
||||
reg = <0x1a>;
|
||||
};
|
|
@ -0,0 +1,78 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/hwmon/jedec,jc42.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Jedec JC-42.4 compatible temperature sensors
|
||||
|
||||
maintainers:
|
||||
- Jean Delvare <jdelvare@suse.com>
|
||||
- Guenter Roeck <linux@roeck-us.net>
|
||||
|
||||
select:
|
||||
properties:
|
||||
compatible:
|
||||
const: jedec,jc-42.4-temp
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: jedec,jc-42.4-temp
|
||||
- items:
|
||||
- enum:
|
||||
- adi,adt7408
|
||||
- atmel,at30ts00
|
||||
- atmel,at30tse004
|
||||
- idt,tse2002
|
||||
- idt,tse2004
|
||||
- idt,ts3000
|
||||
- idt,ts3001
|
||||
- maxim,max6604
|
||||
- microchip,mcp9804
|
||||
- microchip,mcp9805
|
||||
- microchip,mcp9808
|
||||
- microchip,mcp98243
|
||||
- microchip,mcp98244
|
||||
- microchip,mcp9843
|
||||
- nxp,se97
|
||||
- nxp,se97b
|
||||
- nxp,se98
|
||||
- onnn,cat6095
|
||||
- onnn,cat34ts02
|
||||
- st,stts2002
|
||||
- st,stts2004
|
||||
- st,stts3000
|
||||
- st,stts424
|
||||
- st,stts424e
|
||||
- const: jedec,jc-42.4-temp
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
smbus-timeout-disable:
|
||||
description: |
|
||||
When set, the smbus timeout function will be disabled. This is not
|
||||
supported on all chips.
|
||||
type: boolean
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
temp-sensor@1a {
|
||||
compatible = "jedec,jc-42.4-temp";
|
||||
reg = <0x1a>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,41 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/hwmon/lltc,ltc4151.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: LTC4151 High Voltage I2C Current and Voltage Monitor
|
||||
|
||||
maintainers:
|
||||
- Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: lltc,ltc4151
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
shunt-resistor-micro-ohms:
|
||||
description:
|
||||
Shunt resistor value in micro-Ohms
|
||||
default: 1000
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
sensor@6e {
|
||||
compatible = "lltc,ltc4151";
|
||||
reg = <0x6e>;
|
||||
shunt-resistor-micro-ohms = <1500>;
|
||||
};
|
||||
};
|
|
@ -1,22 +0,0 @@
|
|||
* LM70/TMP121/LM71/LM74 thermometer.
|
||||
|
||||
Required properties:
|
||||
- compatible: one of
|
||||
"ti,lm70"
|
||||
"ti,tmp121"
|
||||
"ti,tmp122"
|
||||
"ti,lm71"
|
||||
"ti,lm74"
|
||||
|
||||
See Documentation/devicetree/bindings/spi/spi-bus.txt for more required and
|
||||
optional properties.
|
||||
|
||||
Example:
|
||||
|
||||
spi_master {
|
||||
temperature-sensor@0 {
|
||||
compatible = "ti,lm70";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <1000000>;
|
||||
};
|
||||
};
|
|
@ -1,51 +0,0 @@
|
|||
* LM90 series thermometer.
|
||||
|
||||
Required node properties:
|
||||
- compatible: manufacturer and chip name, one of
|
||||
"adi,adm1032"
|
||||
"adi,adt7461"
|
||||
"adi,adt7461a"
|
||||
"gmt,g781"
|
||||
"national,lm90"
|
||||
"national,lm86"
|
||||
"national,lm89"
|
||||
"national,lm99"
|
||||
"dallas,max6646"
|
||||
"dallas,max6647"
|
||||
"dallas,max6649"
|
||||
"dallas,max6657"
|
||||
"dallas,max6658"
|
||||
"dallas,max6659"
|
||||
"dallas,max6680"
|
||||
"dallas,max6681"
|
||||
"dallas,max6695"
|
||||
"dallas,max6696"
|
||||
"onnn,nct1008"
|
||||
"winbond,w83l771"
|
||||
"nxp,sa56004"
|
||||
"ti,tmp451"
|
||||
|
||||
- reg: I2C bus address of the device
|
||||
|
||||
- vcc-supply: vcc regulator for the supply voltage.
|
||||
|
||||
Optional properties:
|
||||
- interrupts: Contains a single interrupt specifier which describes the
|
||||
LM90 "-ALERT" pin output.
|
||||
See interrupt-controller/interrupts.txt for the format.
|
||||
|
||||
- #thermal-sensor-cells: should be set to 1. See thermal/thermal-sensor.yaml
|
||||
for details. See <include/dt-bindings/thermal/lm90.h> for the
|
||||
definition of the local, remote and 2nd remote sensor index
|
||||
constants.
|
||||
|
||||
Example LM90 node:
|
||||
|
||||
temp-sensor {
|
||||
compatible = "onnn,nct1008";
|
||||
reg = <0x4c>;
|
||||
vcc-supply = <&palmas_ldo6_reg>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <TEGRA_GPIO(O, 4) IRQ_TYPE_LEVEL_LOW>;
|
||||
#thermal-sensor-cells = <1>;
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
LTC4151 High Voltage I2C Current and Voltage Monitor
|
||||
|
||||
Required properties:
|
||||
- compatible: Must be "lltc,ltc4151"
|
||||
- reg: I2C address
|
||||
|
||||
Optional properties:
|
||||
- shunt-resistor-micro-ohms
|
||||
Shunt resistor value in micro-Ohms
|
||||
Defaults to <1000> if unset.
|
||||
|
||||
Example:
|
||||
|
||||
ltc4151@6e {
|
||||
compatible = "lltc,ltc4151";
|
||||
reg = <0x6e>;
|
||||
shunt-resistor-micro-ohms = <1500>;
|
||||
};
|
|
@ -1,21 +0,0 @@
|
|||
mcp3021 properties
|
||||
|
||||
Required properties:
|
||||
- compatible: Must be one of the following:
|
||||
- "microchip,mcp3021" for mcp3021
|
||||
- "microchip,mcp3221" for mcp3221
|
||||
- reg: I2C address
|
||||
|
||||
Optional properties:
|
||||
|
||||
- reference-voltage-microvolt
|
||||
Reference voltage in microvolt (uV)
|
||||
|
||||
Example:
|
||||
|
||||
mcp3021@4d {
|
||||
compatible = "microchip,mcp3021";
|
||||
reg = <0x4d>;
|
||||
|
||||
reference-voltage-microvolt = <4500000>; /* 4.5 V */
|
||||
};
|
|
@ -0,0 +1,43 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/hwmon/microchip,mcp3021.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Microchip MCP3021 A/D converter
|
||||
|
||||
maintainers:
|
||||
- Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- microchip,mcp3021
|
||||
- microchip,mcp3221
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
reference-voltage-microvolt:
|
||||
description:
|
||||
VDD supply power and reference voltage
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
adc@4d {
|
||||
compatible = "microchip,mcp3021";
|
||||
reg = <0x4d>;
|
||||
|
||||
reference-voltage-microvolt = <4500000>; /* 4.5 V */
|
||||
};
|
||||
};
|
|
@ -0,0 +1,78 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/hwmon/national,lm90.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: LM90 series thermometer
|
||||
|
||||
maintainers:
|
||||
- Jean Delvare <jdelvare@suse.com>
|
||||
- Guenter Roeck <linux@roeck-us.net>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- adi,adm1032
|
||||
- adi,adt7461
|
||||
- adi,adt7461a
|
||||
- dallas,max6646
|
||||
- dallas,max6647
|
||||
- dallas,max6649
|
||||
- dallas,max6657
|
||||
- dallas,max6658
|
||||
- dallas,max6659
|
||||
- dallas,max6680
|
||||
- dallas,max6681
|
||||
- dallas,max6695
|
||||
- dallas,max6696
|
||||
- gmt,g781
|
||||
- national,lm86
|
||||
- national,lm89
|
||||
- national,lm90
|
||||
- national,lm99
|
||||
- nxp,sa56004
|
||||
- onnn,nct1008
|
||||
- ti,tmp451
|
||||
- winbond,w83l771
|
||||
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: |
|
||||
Single interrupt specifier which describes the LM90 "-ALERT" pin
|
||||
output.
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
"#thermal-sensor-cells":
|
||||
const: 1
|
||||
|
||||
vcc-supply:
|
||||
description: phandle to the regulator that provides the +VCC supply
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/tegra-gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
sensor@4c {
|
||||
compatible = "onnn,nct1008";
|
||||
reg = <0x4c>;
|
||||
vcc-supply = <&palmas_ldo6_reg>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <TEGRA_GPIO(O, 4) IRQ_TYPE_LEVEL_LOW>;
|
||||
#thermal-sensor-cells = <1>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,141 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
---
|
||||
$id: http://devicetree.org/schemas/hwmon/ntc-thermistor.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: NTC thermistor temperature sensors
|
||||
|
||||
maintainers:
|
||||
- Naveen Krishna Chatradhi <ch.naveen@samsung.com>
|
||||
- Linus Walleij <linus.walleij@linaro.org>
|
||||
|
||||
description: |
|
||||
Thermistors with negative temperature coefficient (NTC) are resistors that
|
||||
vary in resistance in an often non-linear way in relation to temperature.
|
||||
The negative temperature coefficient means that the resistance decreases
|
||||
as the temperature rises. Since the relationship between resistance and
|
||||
temperature is non-linear, software drivers most often need to use a look
|
||||
up table and interpolation to get from resistance to temperature.
|
||||
|
||||
When used in practice, a thermistor is often connected between ground, a
|
||||
pull-up resistor or/and a pull-down resistor and a fixed voltage like this:
|
||||
|
||||
+ e.g. 5V = pull-up voltage (puv)
|
||||
|
|
||||
+-+
|
||||
| |
|
||||
| | Pull-up resistor
|
||||
| | (puo)
|
||||
+-+
|
||||
|-------------------------o
|
||||
+-+ | ^
|
||||
| |/ |
|
||||
| / |
|
||||
|/| Thermistor | Measured voltage (mv)
|
||||
/ | | "connected ground"
|
||||
/| | |
|
||||
+-+ |
|
||||
|-------------------------o
|
||||
+-+ ^
|
||||
| | |
|
||||
| | Pull-down resistor | Measured voltage (mv)
|
||||
| | (pdo) | "connected positive"
|
||||
+-+ |
|
||||
| |
|
||||
| v
|
||||
+ GND GND
|
||||
|
||||
The arrangements of where we measure the voltage over the thermistor are
|
||||
called "connected ground" and "connected positive" and shall be understood as
|
||||
the cases when either pull-up or pull-down resistance is zero.
|
||||
|
||||
If the pull-up resistance is 0 one end of the thermistor is connected to the
|
||||
positive voltage and we get the thermistor on top of a pull-down resistor
|
||||
and we take the measure between the thermistor and the pull-down resistor.
|
||||
|
||||
Conversely if the pull-down resistance is zero, one end of the thermistor is
|
||||
connected to ground and we get the thermistor under the pull-up resistor
|
||||
and we take the measure between the pull-up resistor and the thermistor.
|
||||
|
||||
We can use both pull-up and pull-down resistors at the same time, and then
|
||||
the figure illustrates where the voltage will be measured for the "connected
|
||||
ground" and "connected positive" cases.
|
||||
|
||||
properties:
|
||||
$nodename:
|
||||
pattern: "^thermistor(.*)?$"
|
||||
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: epcos,b57330v2103
|
||||
- const: epcos,b57891s0103
|
||||
- const: murata,ncp15wb473
|
||||
- const: murata,ncp18wb473
|
||||
- const: murata,ncp21wb473
|
||||
- const: murata,ncp03wb473
|
||||
- const: murata,ncp15wl333
|
||||
- const: murata,ncp03wf104
|
||||
- const: murata,ncp15xh103
|
||||
# Deprecated "ntp," compatible strings
|
||||
- const: ntc,ncp15wb473
|
||||
deprecated: true
|
||||
- const: ntc,ncp18wb473
|
||||
deprecated: true
|
||||
- const: ntc,ncp21wb473
|
||||
deprecated: true
|
||||
- const: ntc,ncp03wb473
|
||||
deprecated: true
|
||||
- const: ntc,ncp15wl333
|
||||
deprecated: true
|
||||
|
||||
"#thermal-sensor-cells":
|
||||
description: Thermal sensor cells if used for thermal sensoring.
|
||||
const: 0
|
||||
|
||||
pullup-uv:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: Pull-up voltage in micro volts. Must always be specified.
|
||||
|
||||
pullup-ohm:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: Pull-up resistance in ohms. Must always be specified, even
|
||||
if zero.
|
||||
|
||||
pulldown-ohm:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: Pull-down resistance in ohms. Must always be specified, even
|
||||
if zero.
|
||||
|
||||
connected-positive:
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
description: Indicates how the thermistor is connected in series with
|
||||
a pull-up and/or a pull-down resistor. See the description above for
|
||||
an illustration. If this flag is NOT specified, the thermistor is assumed
|
||||
to be connected-ground, which usually means a pull-down resistance of
|
||||
zero but complex arrangements are possible.
|
||||
|
||||
# See /schemas/iio/adc/adc.yaml
|
||||
io-channels:
|
||||
maxItems: 1
|
||||
description: IIO ADC channel to read the voltage over the resistor. Must
|
||||
always be specified.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- pullup-uv
|
||||
- pullup-ohm
|
||||
- pulldown-ohm
|
||||
- io-channels
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
thermistor0 {
|
||||
compatible = "murata,ncp18wb473";
|
||||
io-channels = <&gpadc 0x06>;
|
||||
pullup-uv = <1800000>;
|
||||
pullup-ohm = <220000>;
|
||||
pulldown-ohm = <0>;
|
||||
#thermal-sensor-cells = <0>;
|
||||
};
|
|
@ -1,44 +0,0 @@
|
|||
NTC Thermistor hwmon sensors
|
||||
-------------------------------
|
||||
|
||||
Requires node properties:
|
||||
- "compatible" value : one of
|
||||
"epcos,b57330v2103"
|
||||
"epcos,b57891s0103"
|
||||
"murata,ncp15wb473"
|
||||
"murata,ncp18wb473"
|
||||
"murata,ncp21wb473"
|
||||
"murata,ncp03wb473"
|
||||
"murata,ncp15wl333"
|
||||
"murata,ncp03wf104"
|
||||
"murata,ncp15xh103"
|
||||
|
||||
/* Usage of vendor name "ntc" is deprecated */
|
||||
<DEPRECATED> "ntc,ncp15wb473"
|
||||
<DEPRECATED> "ntc,ncp18wb473"
|
||||
<DEPRECATED> "ntc,ncp21wb473"
|
||||
<DEPRECATED> "ntc,ncp03wb473"
|
||||
<DEPRECATED> "ntc,ncp15wl333"
|
||||
|
||||
- "pullup-uv" Pull up voltage in micro volts
|
||||
- "pullup-ohm" Pull up resistor value in ohms
|
||||
- "pulldown-ohm" Pull down resistor value in ohms
|
||||
- "connected-positive" Always ON, If not specified.
|
||||
Status change is possible.
|
||||
- "io-channels" Channel node of ADC to be used for
|
||||
conversion.
|
||||
|
||||
Optional node properties:
|
||||
- "#thermal-sensor-cells" Used to expose itself to thermal fw.
|
||||
|
||||
Read more about iio bindings at
|
||||
https://github.com/devicetree-org/dt-schema/blob/master/schemas/iio/
|
||||
|
||||
Example:
|
||||
ncp15wb473@0 {
|
||||
compatible = "murata,ncp15wb473";
|
||||
pullup-uv = <1800000>;
|
||||
pullup-ohm = <47000>;
|
||||
pulldown-ohm = <0>;
|
||||
io-channels = <&adc 3>;
|
||||
};
|
|
@ -0,0 +1,145 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
|
||||
$id: http://devicetree.org/schemas/hwmon/nuvoton,nct7802.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Nuvoton NCT7802Y Hardware Monitoring IC
|
||||
|
||||
maintainers:
|
||||
- Guenter Roeck <linux@roeck-us.net>
|
||||
|
||||
description: |
|
||||
The NCT7802Y is a hardware monitor IC which supports one on-die and up to
|
||||
5 remote temperature sensors with SMBus interface.
|
||||
|
||||
Datasheets:
|
||||
https://www.nuvoton.com/export/resource-files/Nuvoton_NCT7802Y_Datasheet_V12.pdf
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- nuvoton,nct7802
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 0
|
||||
|
||||
patternProperties:
|
||||
"^channel@[0-3]$":
|
||||
type: object
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- enum:
|
||||
- 0 # Local Temperature Sensor ("LTD")
|
||||
- 1 # Remote Temperature Sensor or Voltage Sensor 1 ("RTD1")
|
||||
- 2 # Remote Temperature Sensor or Voltage Sensor 2 ("RTD2")
|
||||
- 3 # Remote Temperature Sensor or Voltage Sensor 3 ("RTD3")
|
||||
|
||||
sensor-type:
|
||||
items:
|
||||
- enum:
|
||||
- temperature
|
||||
- voltage
|
||||
|
||||
temperature-mode:
|
||||
items:
|
||||
- enum:
|
||||
- thermistor
|
||||
- thermal-diode
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
allOf:
|
||||
# For channels RTD1, RTD2 and RTD3, require sensor-type to be set.
|
||||
# Otherwise (for all other channels), do not allow temperature-mode to be
|
||||
# set.
|
||||
- if:
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- enum:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
then:
|
||||
required:
|
||||
- sensor-type
|
||||
else:
|
||||
not:
|
||||
required:
|
||||
- sensor-type
|
||||
|
||||
# For channels RTD1 and RTD2 and if sensor-type is "temperature", require
|
||||
# temperature-mode to be set. Otherwise (for all other channels or
|
||||
# sensor-type settings), do not allow temperature-mode to be set
|
||||
- if:
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- enum:
|
||||
- 1
|
||||
- 2
|
||||
sensor-type:
|
||||
items:
|
||||
- enum:
|
||||
- temperature
|
||||
then:
|
||||
required:
|
||||
- temperature-mode
|
||||
else:
|
||||
not:
|
||||
required:
|
||||
- temperature-mode
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
nct7802@28 {
|
||||
compatible = "nuvoton,nct7802";
|
||||
reg = <0x28>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
channel@0 { /* LTD */
|
||||
reg = <0>;
|
||||
};
|
||||
|
||||
channel@1 { /* RTD1 */
|
||||
reg = <1>;
|
||||
sensor-type = "voltage";
|
||||
};
|
||||
|
||||
channel@2 { /* RTD2 */
|
||||
reg = <2>;
|
||||
sensor-type = "temperature";
|
||||
temperature-mode = "thermal-diode";
|
||||
};
|
||||
|
||||
channel@3 { /* RTD3 */
|
||||
reg = <3>;
|
||||
sensor-type = "temperature";
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,54 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
|
||||
$id: http://devicetree.org/schemas/hwmon/pmbus/ti,lm25066.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: National Semiconductor/Texas Instruments LM250x6/LM506x power-management ICs
|
||||
|
||||
maintainers:
|
||||
- Zev Weiss <zev@bewilderbeest.net>
|
||||
|
||||
description: |
|
||||
The LM25066 family of power-management ICs (a.k.a. hot-swap
|
||||
controllers or eFuses in various contexts) are PMBus devices that
|
||||
offer temperature, current, voltage, and power monitoring.
|
||||
|
||||
Datasheet: https://www.ti.com/lit/ds/symlink/lm25066.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- ti,lm25056
|
||||
- ti,lm25066
|
||||
- ti,lm5064
|
||||
- ti,lm5066
|
||||
- ti,lm5066i
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
shunt-resistor-micro-ohms:
|
||||
description:
|
||||
Shunt (sense) resistor value in micro-Ohms
|
||||
default: 1000
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pmic@40 {
|
||||
compatible = "ti,lm25066";
|
||||
reg = <0x40>;
|
||||
shunt-resistor-micro-ohms = <675>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,43 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/hwmon/sensirion,sht15.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Sensirion SHT15 humidity and temperature sensor
|
||||
|
||||
maintainers:
|
||||
- Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sensirion,sht15
|
||||
|
||||
clk-gpios:
|
||||
maxItems: 1
|
||||
|
||||
data-gpios:
|
||||
maxItems: 1
|
||||
|
||||
vcc-supply:
|
||||
description: regulator that drives the VCC pin
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- clk-gpios
|
||||
- data-gpios
|
||||
- vcc-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
sensor {
|
||||
compatible = "sensirion,sht15";
|
||||
clk-gpios = <&gpio4 12 0>;
|
||||
data-gpios = <&gpio4 13 0>;
|
||||
vcc-supply = <®_sht15>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_sensor>;
|
||||
};
|
|
@ -1,19 +0,0 @@
|
|||
Sensirion SHT15 Humidity and Temperature Sensor
|
||||
|
||||
Required properties:
|
||||
|
||||
- "compatible": must be "sensirion,sht15".
|
||||
- "data-gpios": GPIO connected to the data line.
|
||||
- "clk-gpios": GPIO connected to the clock line.
|
||||
- "vcc-supply": regulator that drives the VCC pin.
|
||||
|
||||
Example:
|
||||
|
||||
sensor {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_sensor>;
|
||||
compatible = "sensirion,sht15";
|
||||
clk-gpios = <&gpio4 12 0>;
|
||||
data-gpios = <&gpio4 13 0>;
|
||||
vcc-supply = <®_sht15>;
|
||||
};
|
|
@ -0,0 +1,47 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/hwmon/ti,tmp102.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: TMP102 temperature sensor
|
||||
|
||||
maintainers:
|
||||
- Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- ti,tmp102
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
"#thermal-sensor-cells":
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
sensor@48 {
|
||||
compatible = "ti,tmp102";
|
||||
reg = <0x48>;
|
||||
interrupt-parent = <&gpio7>;
|
||||
interrupts = <16 IRQ_TYPE_LEVEL_LOW>;
|
||||
#thermal-sensor-cells = <1>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,50 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/hwmon/ti,tmp108.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: TMP108 temperature sensor
|
||||
|
||||
maintainers:
|
||||
- Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- ti,tmp108
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: alert interrupt
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
"#thermal-sensor-cells":
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
sensor@48 {
|
||||
compatible = "ti,tmp108";
|
||||
reg = <0x48>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&tmp_alrt>;
|
||||
#thermal-sensor-cells = <0>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,110 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/hwmon/ti,tmp421.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: TMP42x/TMP44x temperature sensor
|
||||
|
||||
maintainers:
|
||||
- Guenter Roeck <linux@roeck-us.net>
|
||||
|
||||
description: |
|
||||
±1°C Remote and Local temperature sensor
|
||||
https://www.ti.com/lit/ds/symlink/tmp422.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- ti,tmp421
|
||||
- ti,tmp422
|
||||
- ti,tmp423
|
||||
- ti,tmp441
|
||||
- ti,tmp442
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
'#address-cells':
|
||||
const: 1
|
||||
|
||||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
patternProperties:
|
||||
"^channel@([0-3])$":
|
||||
type: object
|
||||
description: |
|
||||
Represents channels of the device and their specific configuration.
|
||||
|
||||
properties:
|
||||
reg:
|
||||
description: |
|
||||
The channel number. 0 is local channel, 1-3 are remote channels
|
||||
items:
|
||||
minimum: 0
|
||||
maximum: 3
|
||||
|
||||
label:
|
||||
description: |
|
||||
A descriptive name for this channel, like "ambient" or "psu".
|
||||
|
||||
ti,n-factor:
|
||||
description: |
|
||||
The value (two's complement) to be programmed in the channel specific N correction register.
|
||||
For remote channels only.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
items:
|
||||
minimum: 0
|
||||
maximum: 255
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
sensor@4c {
|
||||
compatible = "ti,tmp422";
|
||||
reg = <0x4c>;
|
||||
};
|
||||
};
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
sensor@4c {
|
||||
compatible = "ti,tmp422";
|
||||
reg = <0x4c>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
channel@0 {
|
||||
reg = <0x0>;
|
||||
ti,n-factor = <0x1>;
|
||||
label = "local";
|
||||
};
|
||||
|
||||
channel@1 {
|
||||
reg = <0x1>;
|
||||
ti,n-factor = <0x0>;
|
||||
label = "somelabel";
|
||||
};
|
||||
|
||||
channel@2 {
|
||||
reg = <0x2>;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
|
@ -1,18 +0,0 @@
|
|||
TMP108 temperature sensor
|
||||
-------------------------
|
||||
|
||||
This device supports I2C only.
|
||||
|
||||
Requires node properties:
|
||||
- compatible : "ti,tmp108"
|
||||
- reg : the I2C address of the device. This is 0x48, 0x49, 0x4a, or 0x4b.
|
||||
|
||||
Optional properties:
|
||||
- interrupts: Reference to the TMP108 alert interrupt.
|
||||
- #thermal-sensor-cells: should be set to 0.
|
||||
|
||||
Example:
|
||||
tmp108@48 {
|
||||
compatible = "ti,tmp108";
|
||||
reg = <0x48>;
|
||||
};
|
|
@ -41,10 +41,6 @@ properties:
|
|||
- adi,adp5585-02
|
||||
# Analog Devices ADP5589 Keypad Decoder and I/O Expansion
|
||||
- adi,adp5589
|
||||
# +/-1C TDM Extended Temp Range I.C
|
||||
- adi,adt7461
|
||||
# +/-1C TDM Extended Temp Range I.C
|
||||
- adt7461
|
||||
# AMS iAQ-Core VOC Sensor
|
||||
- ams,iaq-core
|
||||
# i2c serial eeprom (24cxx)
|
||||
|
@ -77,6 +73,8 @@ properties:
|
|||
- dallas,ds4510
|
||||
# Digital Thermometer and Thermostat
|
||||
- dallas,ds75
|
||||
# Delta Electronics DPS-650-AB power supply
|
||||
- delta,dps650ab
|
||||
# Delta Electronics DPS920AB 920W 54V Power Supply
|
||||
- delta,dps920ab
|
||||
# 1/4 Brick DC/DC Regulated Power Module
|
||||
|
@ -113,8 +111,14 @@ properties:
|
|||
- mps,mp2888
|
||||
# Monolithic Power Systems Inc. multi-phase controller mp2975
|
||||
- mps,mp2975
|
||||
# G751: Digital Temperature Sensor and Thermal Watchdog with Two-Wire Interface
|
||||
- gmt,g751
|
||||
# Honeywell Humidicon HIH-6130 humidity/temperature sensor
|
||||
- honeywell,hi6130
|
||||
# IBM Common Form Factor Power Supply Versions (all versions)
|
||||
- ibm,cffps
|
||||
# IBM Common Form Factor Power Supply Versions 1
|
||||
- ibm,cffps1
|
||||
# IBM Common Form Factor Power Supply Versions 2
|
||||
- ibm,cffps2
|
||||
# Infineon IR36021 digital POL buck controller
|
||||
- infineon,ir36021
|
||||
# Infineon IR38064 Voltage Regulator
|
||||
|
@ -307,16 +311,22 @@ properties:
|
|||
- ti,hdc1050
|
||||
# Temperature and humidity sensor with i2c interface
|
||||
- ti,hdc1080
|
||||
# Thermometer with SPI interface
|
||||
- ti,lm70
|
||||
- ti,lm71
|
||||
# Temperature sensor with 2-wire interface
|
||||
- ti,lm73
|
||||
# Thermometer with SPI interface
|
||||
- ti,lm74
|
||||
# Temperature sensor with integrated fan control
|
||||
- ti,lm96000
|
||||
# I2C Touch-Screen Controller
|
||||
- ti,tsc2003
|
||||
# Low Power Digital Temperature Sensor with SMBUS/Two Wire Serial Interface
|
||||
- ti,tmp102
|
||||
# Low Power Digital Temperature Sensor with SMBUS/Two Wire Serial Interface
|
||||
- ti,tmp103
|
||||
# Thermometer with SPI interface
|
||||
- ti,tmp121
|
||||
- ti,tmp122
|
||||
# Digital Temperature Sensor
|
||||
- ti,tmp275
|
||||
# TI Dual channel DCAP+ multiphase controller TPS53676 with AVSBus
|
||||
|
|
|
@ -34,6 +34,9 @@ Name Perm Description
|
|||
=============================== ======= =======================================
|
||||
fan[1-3]_input RO Fan speed in RPM.
|
||||
fan[1-3]_label RO Fan label.
|
||||
fan[1-3]_min RO Minimal Fan speed in RPM
|
||||
fan[1-3]_max RO Maximal Fan speed in RPM
|
||||
fan[1-3]_target RO Expected Fan speed in RPM
|
||||
pwm[1-3] RW Control the fan PWM duty-cycle.
|
||||
pwm1_enable WO Enable or disable automatic BIOS fan
|
||||
control (not supported on all laptops,
|
||||
|
|
|
@ -130,6 +130,7 @@ Hardware Monitoring Kernel Drivers
|
|||
max31785
|
||||
max31790
|
||||
max34440
|
||||
max6620
|
||||
max6639
|
||||
max6642
|
||||
max6650
|
||||
|
|
|
@ -79,6 +79,8 @@ This driver does not auto-detect devices. You will have to instantiate the
|
|||
devices explicitly. Please see Documentation/i2c/instantiating-devices.rst for
|
||||
details.
|
||||
|
||||
The shunt (sense) resistor value can be configured by a device tree property;
|
||||
see Documentation/devicetree/bindings/hwmon/pmbus/ti,lm25066.yaml for details.
|
||||
|
||||
Platform data support
|
||||
---------------------
|
||||
|
|
|
@ -265,6 +265,16 @@ Supported chips:
|
|||
|
||||
https://www.ti.com/litv/pdf/sbos686
|
||||
|
||||
* Texas Instruments TMP461
|
||||
|
||||
Prefix: 'tmp461'
|
||||
|
||||
Addresses scanned: I2C 0x48 through 0x4F
|
||||
|
||||
Datasheet: Publicly available at TI website
|
||||
|
||||
https://www.ti.com/lit/gpn/tmp461
|
||||
|
||||
Author: Jean Delvare <jdelvare@suse.de>
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
Kernel driver max6620
|
||||
=====================
|
||||
|
||||
Supported chips:
|
||||
|
||||
Maxim MAX6620
|
||||
|
||||
Prefix: 'max6620'
|
||||
|
||||
Addresses scanned: none
|
||||
|
||||
Datasheet: http://pdfserv.maxim-ic.com/en/ds/MAX6620.pdf
|
||||
|
||||
Authors:
|
||||
- L\. Grunenberg <contact@lgrunenberg.de>
|
||||
- Cumulus Networks <support@cumulusnetworks.com>
|
||||
- Shuotian Cheng <shuche@microsoft.com>
|
||||
- Arun Saravanan Balachandran <Arun_Saravanan_Balac@dell.com>
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
This driver implements support for Maxim MAX6620 fan controller.
|
||||
|
||||
The driver configures the fan controller in RPM mode. To give the readings more
|
||||
range or accuracy, the desired value can be set by a programmable register
|
||||
(1, 2, 4, 8, 16 or 32). Set higher values for larger speeds.
|
||||
|
||||
The driver provides the following sensor access in sysfs:
|
||||
|
||||
================ ======= =====================================================
|
||||
fan[1-4]_alarm ro Fan alarm.
|
||||
fan[1-4]_div rw Sets the nominal RPM range of the fan. Valid values
|
||||
are 1, 2, 4, 8, 16 and 32.
|
||||
fan[1-4]_input ro Fan speed in RPM.
|
||||
fan[1-4]_target rw Desired fan speed in RPM.
|
||||
================ ======= =====================================================
|
||||
|
||||
Usage notes
|
||||
-----------
|
||||
|
||||
This driver does not auto-detect devices. You will have to instantiate the
|
||||
devices explicitly. Please see Documentation/i2c/instantiating-devices.rst for
|
||||
details.
|
|
@ -43,12 +43,6 @@ Supported chips:
|
|||
|
||||
Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp435.html
|
||||
|
||||
* Texas Instruments TMP461
|
||||
|
||||
Prefix: 'tmp461'
|
||||
|
||||
Datasheet: https://www.ti.com/product/tmp461
|
||||
|
||||
|
||||
|
||||
Authors:
|
||||
|
@ -60,7 +54,7 @@ Description
|
|||
-----------
|
||||
|
||||
This driver implements support for Texas Instruments TMP401, TMP411,
|
||||
TMP431, TMP432, TMP435, and TMP461 chips. These chips implement one or two
|
||||
TMP431, TMP432, and TMP435 chips. These chips implement one or two
|
||||
remote and one local temperature sensors. Temperature is measured in degrees
|
||||
Celsius. Resolution of the remote sensor is 0.0625 degree. Local
|
||||
sensor resolution can be set to 0.5, 0.25, 0.125 or 0.0625 degree (not
|
||||
|
@ -84,10 +78,3 @@ some additional features.
|
|||
|
||||
TMP432 is compatible with TMP401 and TMP431. It supports two external
|
||||
temperature sensors.
|
||||
|
||||
TMP461 is compatible with TMP401. It supports offset correction
|
||||
that is applied to the remote sensor.
|
||||
|
||||
* Sensor offset values are temperature values
|
||||
|
||||
Exported via sysfs attribute tempX_offset
|
||||
|
|
|
@ -64,3 +64,13 @@ the temperature values via the following sysfs files:
|
|||
**temp[1-4]_input**
|
||||
|
||||
**temp[2-4]_fault**
|
||||
|
||||
Each sensor can be individually disabled via Devicetree or from sysfs
|
||||
via:
|
||||
|
||||
**temp[1-4]_enable**
|
||||
|
||||
If labels were specified in Devicetree, additional sysfs files will
|
||||
be present:
|
||||
|
||||
**temp[1-4]_label**
|
||||
|
|
|
@ -10038,6 +10038,7 @@ JC42.4 TEMPERATURE SENSOR DRIVER
|
|||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/hwmon/jedec,jc42.yaml
|
||||
F: Documentation/hwmon/jc42.rst
|
||||
F: drivers/hwmon/jc42.c
|
||||
|
||||
|
@ -10932,7 +10933,7 @@ LM90 HARDWARE MONITOR DRIVER
|
|||
M: Jean Delvare <jdelvare@suse.com>
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/hwmon/lm90.txt
|
||||
F: Documentation/devicetree/bindings/hwmon/national,lm90.yaml
|
||||
F: Documentation/hwmon/lm90.rst
|
||||
F: drivers/hwmon/lm90.c
|
||||
F: include/dt-bindings/thermal/lm90.h
|
||||
|
@ -14966,7 +14967,6 @@ S: Maintained
|
|||
W: http://hwmon.wiki.kernel.org/
|
||||
W: http://www.roeck-us.net/linux/drivers/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
|
||||
F: Documentation/devicetree/bindings/hwmon/ibm,cffps1.txt
|
||||
F: Documentation/devicetree/bindings/hwmon/ltc2978.txt
|
||||
F: Documentation/devicetree/bindings/hwmon/max31785.txt
|
||||
F: Documentation/hwmon/adm1275.rst
|
||||
|
|
|
@ -608,6 +608,7 @@ struct acpi_device *acpi_bus_get_acpi_device(acpi_handle handle)
|
|||
{
|
||||
return handle_to_device(handle, get_acpi_device);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_bus_get_acpi_device);
|
||||
|
||||
static struct acpi_device_bus_id *acpi_device_bus_id_match(const char *dev_id)
|
||||
{
|
||||
|
|
|
@ -1032,6 +1032,16 @@ config SENSORS_MAX31730
|
|||
This driver can also be built as a module. If so, the module
|
||||
will be called max31730.
|
||||
|
||||
config SENSORS_MAX6620
|
||||
tristate "Maxim MAX6620 fan controller"
|
||||
depends on I2C
|
||||
help
|
||||
If you say yes here you get support for the MAX6620
|
||||
fan controller.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called max6620.
|
||||
|
||||
config SENSORS_MAX6621
|
||||
tristate "Maxim MAX6621 sensor chip"
|
||||
depends on I2C
|
||||
|
@ -1317,7 +1327,7 @@ config SENSORS_LM90
|
|||
Maxim MAX6646, MAX6647, MAX6648, MAX6649, MAX6654, MAX6657, MAX6658,
|
||||
MAX6659, MAX6680, MAX6681, MAX6692, MAX6695, MAX6696,
|
||||
ON Semiconductor NCT1008, Winbond/Nuvoton W83L771W/G/AWG/ASG,
|
||||
Philips SA56004, GMT G781, and Texas Instruments TMP451
|
||||
Philips SA56004, GMT G781, Texas Instruments TMP451 and TMP461
|
||||
sensor chips.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
|
@ -1433,6 +1443,7 @@ config SENSORS_NCT6683
|
|||
config SENSORS_NCT6775
|
||||
tristate "Nuvoton NCT6775F and compatibles"
|
||||
depends on !PPC
|
||||
depends on ACPI_WMI || ACPI_WMI=n
|
||||
select HWMON_VID
|
||||
help
|
||||
If you say yes here you get support for the hardware monitoring
|
||||
|
@ -1930,7 +1941,7 @@ config SENSORS_TMP401
|
|||
depends on I2C
|
||||
help
|
||||
If you say yes here you get support for Texas Instruments TMP401,
|
||||
TMP411, TMP431, TMP432, TMP435, and TMP461 temperature sensor chips.
|
||||
TMP411, TMP431, TMP432, and TMP435 temperature sensor chips.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called tmp401.
|
||||
|
|
|
@ -135,6 +135,7 @@ obj-$(CONFIG_SENSORS_MAX1668) += max1668.o
|
|||
obj-$(CONFIG_SENSORS_MAX197) += max197.o
|
||||
obj-$(CONFIG_SENSORS_MAX31722) += max31722.o
|
||||
obj-$(CONFIG_SENSORS_MAX31730) += max31730.o
|
||||
obj-$(CONFIG_SENSORS_MAX6620) += max6620.o
|
||||
obj-$(CONFIG_SENSORS_MAX6621) += max6621.o
|
||||
obj-$(CONFIG_SENSORS_MAX6639) += max6639.o
|
||||
obj-$(CONFIG_SENSORS_MAX6642) += max6642.o
|
||||
|
|
|
@ -145,7 +145,7 @@ struct abituguru3_data {
|
|||
struct device *hwmon_dev; /* hwmon registered device */
|
||||
struct mutex update_lock; /* protect access to data and uGuru */
|
||||
unsigned short addr; /* uguru base address */
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
bool valid; /* true if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
|
||||
/*
|
||||
|
@ -1083,7 +1083,7 @@ static struct abituguru3_data *abituguru3_update_device(struct device *dev)
|
|||
mutex_lock(&data->update_lock);
|
||||
if (!data->valid || time_after(jiffies, data->last_updated + HZ)) {
|
||||
/* Clear data->valid while updating */
|
||||
data->valid = 0;
|
||||
data->valid = false;
|
||||
/* Read alarms */
|
||||
if (abituguru3_read_increment_offset(data,
|
||||
ABIT_UGURU3_SETTINGS_BANK,
|
||||
|
@ -1117,7 +1117,7 @@ static struct abituguru3_data *abituguru3_update_device(struct device *dev)
|
|||
goto LEAVE_UPDATE;
|
||||
}
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
LEAVE_UPDATE:
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -535,7 +535,7 @@ static void remove_domain_devices(struct acpi_power_meter_resource *resource)
|
|||
|
||||
sysfs_remove_link(resource->holders_dir,
|
||||
kobject_name(&obj->dev.kobj));
|
||||
put_device(&obj->dev);
|
||||
acpi_dev_put(obj);
|
||||
}
|
||||
|
||||
kfree(resource->domain_devices);
|
||||
|
@ -597,18 +597,15 @@ static int read_domain_devices(struct acpi_power_meter_resource *resource)
|
|||
continue;
|
||||
|
||||
/* Create a symlink to domain objects */
|
||||
resource->domain_devices[i] = NULL;
|
||||
if (acpi_bus_get_device(element->reference.handle,
|
||||
&resource->domain_devices[i]))
|
||||
obj = acpi_bus_get_acpi_device(element->reference.handle);
|
||||
resource->domain_devices[i] = obj;
|
||||
if (!obj)
|
||||
continue;
|
||||
|
||||
obj = resource->domain_devices[i];
|
||||
get_device(&obj->dev);
|
||||
|
||||
res = sysfs_create_link(resource->holders_dir, &obj->dev.kobj,
|
||||
kobject_name(&obj->dev.kobj));
|
||||
if (res) {
|
||||
put_device(&obj->dev);
|
||||
acpi_dev_put(obj);
|
||||
resource->domain_devices[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ static u8 AD7414_REG_LIMIT[] = { AD7414_REG_T_HIGH, AD7414_REG_T_LOW };
|
|||
struct ad7414_data {
|
||||
struct i2c_client *client;
|
||||
struct mutex lock; /* atomic read data updates */
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
bool valid; /* true if following fields are valid */
|
||||
unsigned long next_update; /* In jiffies */
|
||||
s16 temp_input; /* Register values */
|
||||
s8 temps[ARRAY_SIZE(AD7414_REG_LIMIT)];
|
||||
|
@ -95,7 +95,7 @@ static struct ad7414_data *ad7414_update_device(struct device *dev)
|
|||
}
|
||||
|
||||
data->next_update = jiffies + HZ + HZ / 2;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->lock);
|
||||
|
|
|
@ -46,7 +46,7 @@ struct ad7418_data {
|
|||
enum chips type;
|
||||
struct mutex lock;
|
||||
int adc_max; /* number of ADC channels */
|
||||
char valid;
|
||||
bool valid;
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
s16 temp[3]; /* Register values */
|
||||
u16 in[4];
|
||||
|
@ -111,14 +111,14 @@ static int ad7418_update_device(struct device *dev)
|
|||
goto abort;
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->lock);
|
||||
return 0;
|
||||
|
||||
abort:
|
||||
data->valid = 0;
|
||||
data->valid = false;
|
||||
mutex_unlock(&data->lock);
|
||||
return val;
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ struct adm1021_data {
|
|||
const struct attribute_group *groups[3];
|
||||
|
||||
struct mutex update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
bool valid; /* true if following fields are valid */
|
||||
char low_power; /* !=0 if device in low power mode */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
|
||||
|
@ -135,7 +135,7 @@ static struct adm1021_data *adm1021_update_device(struct device *dev)
|
|||
ADM1023_REG_REM_OFFSET_PREC);
|
||||
}
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -97,7 +97,7 @@ struct adm1025_data {
|
|||
struct i2c_client *client;
|
||||
const struct attribute_group *groups[3];
|
||||
struct mutex update_lock;
|
||||
char valid; /* zero until following fields are valid */
|
||||
bool valid; /* false until following fields are valid */
|
||||
unsigned long last_updated; /* in jiffies */
|
||||
|
||||
u8 in[6]; /* register value */
|
||||
|
@ -148,7 +148,7 @@ static struct adm1025_data *adm1025_update_device(struct device *dev)
|
|||
ADM1025_REG_VID4) & 0x01) << 4);
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -259,7 +259,7 @@ struct adm1026_data {
|
|||
const struct attribute_group *groups[3];
|
||||
|
||||
struct mutex update_lock;
|
||||
int valid; /* !=0 if following fields are valid */
|
||||
bool valid; /* true if following fields are valid */
|
||||
unsigned long last_reading; /* In jiffies */
|
||||
unsigned long last_config; /* In jiffies */
|
||||
|
||||
|
@ -459,7 +459,7 @@ static struct adm1026_data *adm1026_update_device(struct device *dev)
|
|||
data->last_config = jiffies;
|
||||
} /* last_config */
|
||||
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
mutex_unlock(&data->update_lock);
|
||||
return data;
|
||||
}
|
||||
|
|
|
@ -99,7 +99,7 @@ static const u8 ADM1029_REG_FAN_DIV[] = {
|
|||
struct adm1029_data {
|
||||
struct i2c_client *client;
|
||||
struct mutex update_lock; /* protect register access */
|
||||
char valid; /* zero until following fields are valid */
|
||||
bool valid; /* false until following fields are valid */
|
||||
unsigned long last_updated; /* in jiffies */
|
||||
|
||||
/* registers values, signed for temperature, unsigned for other stuff */
|
||||
|
@ -143,7 +143,7 @@ static struct adm1029_data *adm1029_update_device(struct device *dev)
|
|||
}
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -65,7 +65,7 @@ struct adm1031_data {
|
|||
const struct attribute_group *groups[3];
|
||||
struct mutex update_lock;
|
||||
int chip_type;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
bool valid; /* true if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
unsigned int update_interval; /* In milliseconds */
|
||||
/*
|
||||
|
@ -187,7 +187,7 @@ static struct adm1031_data *adm1031_update_device(struct device *dev)
|
|||
ADM1031_REG_PWM) >> (4 * chan)) & 0x0f;
|
||||
}
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
@ -650,7 +650,7 @@ static ssize_t fan_div_store(struct device *dev,
|
|||
data->fan_min[nr]);
|
||||
|
||||
/* Invalidate the cache: fan speed is no longer valid */
|
||||
data->valid = 0;
|
||||
data->valid = false;
|
||||
mutex_unlock(&data->update_lock);
|
||||
return count;
|
||||
}
|
||||
|
|
|
@ -90,7 +90,8 @@ static int adt7310_spi_probe(struct spi_device *spi)
|
|||
|
||||
static int adt7310_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
return adt7x10_remove(&spi->dev, spi->irq);
|
||||
adt7x10_remove(&spi->dev, spi->irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct spi_device_id adt7310_id[] = {
|
||||
|
|
|
@ -50,7 +50,8 @@ static int adt7410_i2c_probe(struct i2c_client *client)
|
|||
|
||||
static int adt7410_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
return adt7x10_remove(&client->dev, client->irq);
|
||||
adt7x10_remove(&client->dev, client->irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id adt7410_ids[] = {
|
||||
|
|
|
@ -444,7 +444,7 @@ exit_restore:
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(adt7x10_probe);
|
||||
|
||||
int adt7x10_remove(struct device *dev, int irq)
|
||||
void adt7x10_remove(struct device *dev, int irq)
|
||||
{
|
||||
struct adt7x10_data *data = dev_get_drvdata(dev);
|
||||
|
||||
|
@ -457,7 +457,6 @@ int adt7x10_remove(struct device *dev, int irq)
|
|||
sysfs_remove_group(&dev->kobj, &adt7x10_group);
|
||||
if (data->oldconfig != data->config)
|
||||
adt7x10_write_byte(dev, ADT7X10_CONFIG, data->oldconfig);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(adt7x10_remove);
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ struct adt7x10_ops {
|
|||
|
||||
int adt7x10_probe(struct device *dev, const char *name, int irq,
|
||||
const struct adt7x10_ops *ops);
|
||||
int adt7x10_remove(struct device *dev, int irq);
|
||||
void adt7x10_remove(struct device *dev, int irq);
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
extern const struct dev_pm_ops adt7x10_dev_pm_ops;
|
||||
|
|
|
@ -141,7 +141,7 @@ static const u8 fan_reg_hi[] = {AMC6821_REG_TDATA_HI,
|
|||
struct amc6821_data {
|
||||
struct i2c_client *client;
|
||||
struct mutex update_lock;
|
||||
char valid; /* zero until following fields are valid */
|
||||
bool valid; /* false until following fields are valid */
|
||||
unsigned long last_updated; /* in jiffies */
|
||||
|
||||
/* register values */
|
||||
|
@ -258,7 +258,7 @@ static struct amc6821_data *amc6821_update_device(struct device *dev)
|
|||
}
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
mutex_unlock(&data->update_lock);
|
||||
return data;
|
||||
|
@ -511,7 +511,7 @@ static ssize_t temp_auto_point_temp_store(struct device *dev,
|
|||
}
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->valid = 0;
|
||||
data->valid = false;
|
||||
|
||||
switch (ix) {
|
||||
case 0:
|
||||
|
@ -584,7 +584,7 @@ static ssize_t pwm1_auto_point_pwm_store(struct device *dev,
|
|||
}
|
||||
|
||||
EXIT:
|
||||
data->valid = 0;
|
||||
data->valid = false;
|
||||
mutex_unlock(&data->update_lock);
|
||||
return count;
|
||||
}
|
||||
|
|
|
@ -391,7 +391,7 @@ static const struct applesmc_entry *applesmc_get_entry_by_index(int index)
|
|||
cache->len = info[0];
|
||||
memcpy(cache->type, &info[1], 4);
|
||||
cache->flags = info[5];
|
||||
cache->valid = 1;
|
||||
cache->valid = true;
|
||||
|
||||
out:
|
||||
mutex_unlock(&smcreg.mutex);
|
||||
|
|
|
@ -186,7 +186,7 @@ struct asb100_data {
|
|||
/* array of 2 pointers to subclients */
|
||||
struct i2c_client *lm75[2];
|
||||
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
bool valid; /* true if following fields are valid */
|
||||
u8 in[7]; /* Register value */
|
||||
u8 in_max[7]; /* Register value */
|
||||
u8 in_min[7]; /* Register value */
|
||||
|
@ -993,7 +993,7 @@ static struct asb100_data *asb100_update_device(struct device *dev)
|
|||
(asb100_read_value(client, ASB100_REG_ALARM2) << 8);
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
|
||||
dev_dbg(&client->dev, "... device update complete\n");
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ struct asc7621_data {
|
|||
struct i2c_client client;
|
||||
struct device *class_dev;
|
||||
struct mutex update_lock;
|
||||
int valid; /* !=0 if following fields are valid */
|
||||
bool valid; /* true if following fields are valid */
|
||||
unsigned long last_high_reading; /* In jiffies */
|
||||
unsigned long last_low_reading; /* In jiffies */
|
||||
/*
|
||||
|
@ -1032,7 +1032,7 @@ static struct asc7621_data *asc7621_update_device(struct device *dev)
|
|||
data->last_low_reading = jiffies;
|
||||
} /* last_reading */
|
||||
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ struct atxp1_data {
|
|||
struct i2c_client *client;
|
||||
struct mutex update_lock;
|
||||
unsigned long last_updated;
|
||||
u8 valid;
|
||||
bool valid;
|
||||
struct {
|
||||
u8 vid; /* VID output register */
|
||||
u8 cpu_vid; /* VID input from CPU */
|
||||
|
@ -63,7 +63,7 @@ static struct atxp1_data *atxp1_update_device(struct device *dev)
|
|||
data->reg.gpio1 = i2c_smbus_read_byte_data(client, ATXP1_GPIO1);
|
||||
data->reg.gpio2 = i2c_smbus_read_byte_data(client, ATXP1_GPIO2);
|
||||
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
@ -136,7 +136,7 @@ static ssize_t cpu0_vid_store(struct device *dev,
|
|||
ATXP1_VID, cvid | ATXP1_VIDENA);
|
||||
}
|
||||
|
||||
data->valid = 0;
|
||||
data->valid = false;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ static ssize_t gpio1_store(struct device *dev, struct device_attribute *attr,
|
|||
|
||||
i2c_smbus_write_byte_data(client, ATXP1_GPIO1, value);
|
||||
|
||||
data->valid = 0;
|
||||
data->valid = false;
|
||||
}
|
||||
|
||||
return count;
|
||||
|
@ -224,7 +224,7 @@ static ssize_t gpio2_store(struct device *dev, struct device_attribute *attr,
|
|||
|
||||
i2c_smbus_write_byte_data(client, ATXP1_GPIO2, value);
|
||||
|
||||
data->valid = 0;
|
||||
data->valid = false;
|
||||
}
|
||||
|
||||
return count;
|
||||
|
|
|
@ -167,7 +167,7 @@ static ssize_t show_temp(struct device *dev,
|
|||
* really help at all.
|
||||
*/
|
||||
tdata->temp = tdata->tjmax - ((eax >> 16) & 0x7f) * 1000;
|
||||
tdata->valid = 1;
|
||||
tdata->valid = true;
|
||||
tdata->last_updated = jiffies;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,24 +12,24 @@
|
|||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/capability.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/capability.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <linux/i8k.h>
|
||||
|
||||
|
@ -76,6 +76,7 @@ struct dell_smm_data {
|
|||
int temp_type[DELL_SMM_NO_TEMP];
|
||||
bool fan[DELL_SMM_NO_FANS];
|
||||
int fan_type[DELL_SMM_NO_FANS];
|
||||
int *fan_nominal_speed[DELL_SMM_NO_FANS];
|
||||
};
|
||||
|
||||
MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)");
|
||||
|
@ -326,7 +327,7 @@ static int i8k_enable_fan_auto_mode(const struct dell_smm_data *data, bool enabl
|
|||
}
|
||||
|
||||
/*
|
||||
* Set the fan speed (off, low, high). Returns the new fan status.
|
||||
* Set the fan speed (off, low, high, ...).
|
||||
*/
|
||||
static int i8k_set_fan(const struct dell_smm_data *data, int fan, int speed)
|
||||
{
|
||||
|
@ -338,7 +339,7 @@ static int i8k_set_fan(const struct dell_smm_data *data, int fan, int speed)
|
|||
speed = (speed < 0) ? 0 : ((speed > data->i8k_fan_max) ? data->i8k_fan_max : speed);
|
||||
regs.ebx = (fan & 0xff) | (speed << 8);
|
||||
|
||||
return i8k_smm(®s) ? : i8k_get_fan_status(data, fan);
|
||||
return i8k_smm(®s);
|
||||
}
|
||||
|
||||
static int __init i8k_get_temp_type(int sensor)
|
||||
|
@ -452,7 +453,7 @@ static int
|
|||
i8k_ioctl_unlocked(struct file *fp, struct dell_smm_data *data, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int val = 0;
|
||||
int speed;
|
||||
int speed, err;
|
||||
unsigned char buff[16];
|
||||
int __user *argp = (int __user *)arg;
|
||||
|
||||
|
@ -473,8 +474,7 @@ i8k_ioctl_unlocked(struct file *fp, struct dell_smm_data *data, unsigned int cmd
|
|||
if (restricted && !capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
memset(buff, 0, sizeof(buff));
|
||||
strscpy(buff, data->bios_machineid, sizeof(buff));
|
||||
strscpy_pad(buff, data->bios_machineid, sizeof(buff));
|
||||
break;
|
||||
|
||||
case I8K_FN_STATUS:
|
||||
|
@ -513,11 +513,15 @@ i8k_ioctl_unlocked(struct file *fp, struct dell_smm_data *data, unsigned int cmd
|
|||
if (copy_from_user(&speed, argp + 1, sizeof(int)))
|
||||
return -EFAULT;
|
||||
|
||||
val = i8k_set_fan(data, val, speed);
|
||||
err = i8k_set_fan(data, val, speed);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
val = i8k_get_fan_status(data, val);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
|
||||
if (val < 0)
|
||||
|
@ -673,6 +677,13 @@ static umode_t dell_smm_is_visible(const void *drvdata, enum hwmon_sensor_types
|
|||
if (data->fan[channel] && !data->disallow_fan_type_call)
|
||||
return 0444;
|
||||
|
||||
break;
|
||||
case hwmon_fan_min:
|
||||
case hwmon_fan_max:
|
||||
case hwmon_fan_target:
|
||||
if (data->fan_nominal_speed[channel])
|
||||
return 0444;
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -740,6 +751,25 @@ static int dell_smm_read(struct device *dev, enum hwmon_sensor_types type, u32 a
|
|||
|
||||
*val = ret;
|
||||
|
||||
return 0;
|
||||
case hwmon_fan_min:
|
||||
*val = data->fan_nominal_speed[channel][0];
|
||||
|
||||
return 0;
|
||||
case hwmon_fan_max:
|
||||
*val = data->fan_nominal_speed[channel][data->i8k_fan_max];
|
||||
|
||||
return 0;
|
||||
case hwmon_fan_target:
|
||||
ret = i8k_get_fan_status(data, channel);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ret > data->i8k_fan_max)
|
||||
ret = data->i8k_fan_max;
|
||||
|
||||
*val = data->fan_nominal_speed[channel][ret];
|
||||
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
|
@ -889,9 +919,12 @@ static const struct hwmon_channel_info *dell_smm_info[] = {
|
|||
HWMON_T_INPUT | HWMON_T_LABEL
|
||||
),
|
||||
HWMON_CHANNEL_INFO(fan,
|
||||
HWMON_F_INPUT | HWMON_F_LABEL,
|
||||
HWMON_F_INPUT | HWMON_F_LABEL,
|
||||
HWMON_F_INPUT | HWMON_F_LABEL
|
||||
HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MIN | HWMON_F_MAX |
|
||||
HWMON_F_TARGET,
|
||||
HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MIN | HWMON_F_MAX |
|
||||
HWMON_F_TARGET,
|
||||
HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MIN | HWMON_F_MAX |
|
||||
HWMON_F_TARGET
|
||||
),
|
||||
HWMON_CHANNEL_INFO(pwm,
|
||||
HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
|
||||
|
@ -910,7 +943,7 @@ static int __init dell_smm_init_hwmon(struct device *dev)
|
|||
{
|
||||
struct dell_smm_data *data = dev_get_drvdata(dev);
|
||||
struct device *dell_smm_hwmon_dev;
|
||||
int i, err;
|
||||
int i, state, err;
|
||||
|
||||
for (i = 0; i < DELL_SMM_NO_TEMP; i++) {
|
||||
data->temp_type[i] = i8k_get_temp_type(i);
|
||||
|
@ -926,8 +959,27 @@ static int __init dell_smm_init_hwmon(struct device *dev)
|
|||
err = i8k_get_fan_status(data, i);
|
||||
if (err < 0)
|
||||
err = i8k_get_fan_type(data, i);
|
||||
if (err >= 0)
|
||||
data->fan[i] = true;
|
||||
|
||||
if (err < 0)
|
||||
continue;
|
||||
|
||||
data->fan[i] = true;
|
||||
data->fan_nominal_speed[i] = devm_kmalloc_array(dev, data->i8k_fan_max + 1,
|
||||
sizeof(*data->fan_nominal_speed[i]),
|
||||
GFP_KERNEL);
|
||||
if (!data->fan_nominal_speed[i])
|
||||
continue;
|
||||
|
||||
for (state = 0; state <= data->i8k_fan_max; state++) {
|
||||
err = i8k_get_fan_nominal_speed(data, i, state);
|
||||
if (err < 0) {
|
||||
/* Mark nominal speed table as invalid in case of error */
|
||||
devm_kfree(dev, data->fan_nominal_speed[i]);
|
||||
data->fan_nominal_speed[i] = NULL;
|
||||
break;
|
||||
}
|
||||
data->fan_nominal_speed[i][state] = err;
|
||||
}
|
||||
}
|
||||
|
||||
dell_smm_hwmon_dev = devm_hwmon_device_register_with_info(dev, "dell_smm", data,
|
||||
|
@ -948,6 +1000,11 @@ enum i8k_configs {
|
|||
DELL_XPS,
|
||||
};
|
||||
|
||||
/*
|
||||
* Only use for machines which need some special configuration
|
||||
* in order to work correctly (e.g. if autoconfig fails on this machines).
|
||||
*/
|
||||
|
||||
static const struct i8k_config_data i8k_config_data[] __initconst = {
|
||||
[DELL_LATITUDE_D520] = {
|
||||
.fan_mult = 1,
|
||||
|
|
|
@ -203,7 +203,7 @@ struct dme1737_data {
|
|||
unsigned int addr; /* for ISA devices only */
|
||||
|
||||
struct mutex update_lock;
|
||||
int valid; /* !=0 if following fields are valid */
|
||||
bool valid; /* true if following fields are valid */
|
||||
unsigned long last_update; /* in jiffies */
|
||||
unsigned long last_vbat; /* in jiffies */
|
||||
enum chips type;
|
||||
|
@ -778,7 +778,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
|
|||
}
|
||||
|
||||
data->last_update = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -109,7 +109,7 @@ static const u8 DS1621_REG_TEMP[3] = {
|
|||
struct ds1621_data {
|
||||
struct i2c_client *client;
|
||||
struct mutex update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
bool valid; /* true if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
enum chips kind; /* device type */
|
||||
|
||||
|
@ -213,7 +213,7 @@ static struct ds1621_data *ds1621_update_client(struct device *dev)
|
|||
new_conf);
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -56,7 +56,7 @@ static const u8 DS620_REG_TEMP[3] = {
|
|||
struct ds620_data {
|
||||
struct i2c_client *client;
|
||||
struct mutex update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
bool valid; /* true if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
|
||||
s16 temp[3]; /* Register values, word */
|
||||
|
@ -118,7 +118,7 @@ static struct ds620_data *ds620_update_client(struct device *dev)
|
|||
}
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
abort:
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -45,7 +45,7 @@ enum subfeature { input, min, max };
|
|||
struct emc6w201_data {
|
||||
struct i2c_client *client;
|
||||
struct mutex update_lock;
|
||||
char valid; /* zero until following fields are valid */
|
||||
bool valid; /* false until following fields are valid */
|
||||
unsigned long last_updated; /* in jiffies */
|
||||
|
||||
/* registers values */
|
||||
|
@ -162,7 +162,7 @@ static struct emc6w201_data *emc6w201_update_device(struct device *dev)
|
|||
}
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -165,7 +165,7 @@ struct f71805f_data {
|
|||
struct device *hwmon_dev;
|
||||
|
||||
struct mutex update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
bool valid; /* true if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
unsigned long last_limits; /* In jiffies */
|
||||
|
||||
|
@ -404,7 +404,7 @@ static struct f71805f_data *f71805f_update_device(struct device *dev)
|
|||
+ (f71805f_read8(data, F71805F_REG_STATUS(2)) << 16);
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -253,7 +253,7 @@ struct f71882fg_data {
|
|||
|
||||
struct mutex update_lock;
|
||||
int temp_start; /* temp numbering start (0 or 1) */
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
bool valid; /* true if following fields are valid */
|
||||
char auto_point_temp_signed;
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
unsigned long last_limits; /* In jiffies */
|
||||
|
@ -1359,7 +1359,7 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
|
|||
F71882FG_REG_IN(nr));
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -85,7 +85,7 @@ struct f75375_data {
|
|||
const char *name;
|
||||
int kind;
|
||||
struct mutex update_lock; /* protect register access */
|
||||
char valid;
|
||||
bool valid;
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
unsigned long last_limits; /* In jiffies */
|
||||
|
||||
|
@ -228,7 +228,7 @@ static struct f75375_data *f75375_update_device(struct device *dev)
|
|||
f75375_read8(client, F75375_REG_VOLT(nr));
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -264,7 +264,7 @@ struct fschmd_data {
|
|||
unsigned long watchdog_is_open;
|
||||
char watchdog_expect_close;
|
||||
char watchdog_name[10]; /* must be unique to avoid sysfs conflict */
|
||||
char valid; /* zero until following fields are valid */
|
||||
bool valid; /* false until following fields are valid */
|
||||
unsigned long last_updated; /* in jiffies */
|
||||
|
||||
/* register values */
|
||||
|
@ -1356,7 +1356,7 @@ static struct fschmd_data *fschmd_update_device(struct device *dev)
|
|||
FSCHMD_REG_VOLT[data->kind][i]);
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -95,7 +95,7 @@ static struct g760a_data *g760a_update_client(struct device *dev)
|
|||
data->fan_sta = g760a_read_value(client, G760A_REG_FAN_STA);
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -107,7 +107,7 @@ struct gl518_data {
|
|||
enum chips type;
|
||||
|
||||
struct mutex update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
bool valid; /* true if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
|
||||
u8 voltage_in[4]; /* Register values; [0] = VDD */
|
||||
|
@ -211,7 +211,7 @@ static struct gl518_data *gl518_update_device(struct device *dev)
|
|||
gl518_read_value(client, GL518_REG_VIN3);
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -64,7 +64,7 @@ struct gl520_data {
|
|||
struct i2c_client *client;
|
||||
const struct attribute_group *groups[3];
|
||||
struct mutex update_lock;
|
||||
char valid; /* zero until the following fields are valid */
|
||||
bool valid; /* false until the following fields are valid */
|
||||
unsigned long last_updated; /* in jiffies */
|
||||
|
||||
u8 vid;
|
||||
|
@ -174,7 +174,7 @@ static struct gl520_data *gl520_update_device(struct device *dev)
|
|||
}
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -796,8 +796,10 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata,
|
|||
dev_set_drvdata(hdev, drvdata);
|
||||
dev_set_name(hdev, HWMON_ID_FORMAT, id);
|
||||
err = device_register(hdev);
|
||||
if (err)
|
||||
goto free_hwmon;
|
||||
if (err) {
|
||||
put_device(hdev);
|
||||
goto ida_remove;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&hwdev->tzdata);
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* Copyright (C) 2012, 2014 Jean Delvare <jdelvare@suse.de>
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -12,7 +13,6 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
|
@ -29,69 +29,78 @@
|
|||
#define REG_CTCTRL 0xF7
|
||||
#define REG_TSTIMER 0xF8
|
||||
|
||||
/*
|
||||
* Sysfs stuff
|
||||
*/
|
||||
|
||||
/* Sensor resolution : 0.5 degree C */
|
||||
static ssize_t temp1_input_show(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
static umode_t i5500_is_visible(const void *drvdata, enum hwmon_sensor_types type, u32 attr,
|
||||
int channel)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev->parent);
|
||||
long temp;
|
||||
u16 tsthrhi;
|
||||
s8 tsfsc;
|
||||
|
||||
pci_read_config_word(pdev, REG_TSTHRHI, &tsthrhi);
|
||||
pci_read_config_byte(pdev, REG_TSFSC, &tsfsc);
|
||||
temp = ((long)tsthrhi - tsfsc) * 500;
|
||||
|
||||
return sprintf(buf, "%ld\n", temp);
|
||||
return 0444;
|
||||
}
|
||||
|
||||
static ssize_t thresh_show(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
static int i5500_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel,
|
||||
long *val)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev->parent);
|
||||
int reg = to_sensor_dev_attr(devattr)->index;
|
||||
long temp;
|
||||
u16 tsthr;
|
||||
|
||||
pci_read_config_word(pdev, reg, &tsthr);
|
||||
temp = tsthr * 500;
|
||||
|
||||
return sprintf(buf, "%ld\n", temp);
|
||||
}
|
||||
|
||||
static ssize_t alarm_show(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev->parent);
|
||||
int nr = to_sensor_dev_attr(devattr)->index;
|
||||
s8 tsfsc;
|
||||
u8 ctsts;
|
||||
|
||||
pci_read_config_byte(pdev, REG_CTSTS, &ctsts);
|
||||
return sprintf(buf, "%u\n", (unsigned int)ctsts & (1 << nr));
|
||||
switch (type) {
|
||||
case hwmon_temp:
|
||||
switch (attr) {
|
||||
/* Sensor resolution : 0.5 degree C */
|
||||
case hwmon_temp_input:
|
||||
pci_read_config_word(pdev, REG_TSTHRHI, &tsthr);
|
||||
pci_read_config_byte(pdev, REG_TSFSC, &tsfsc);
|
||||
*val = (tsthr - tsfsc) * 500;
|
||||
return 0;
|
||||
case hwmon_temp_max:
|
||||
pci_read_config_word(pdev, REG_TSTHRHI, &tsthr);
|
||||
*val = tsthr * 500;
|
||||
return 0;
|
||||
case hwmon_temp_max_hyst:
|
||||
pci_read_config_word(pdev, REG_TSTHRLO, &tsthr);
|
||||
*val = tsthr * 500;
|
||||
return 0;
|
||||
case hwmon_temp_crit:
|
||||
pci_read_config_word(pdev, REG_TSTHRCATA, &tsthr);
|
||||
*val = tsthr * 500;
|
||||
return 0;
|
||||
case hwmon_temp_max_alarm:
|
||||
pci_read_config_byte(pdev, REG_CTSTS, &ctsts);
|
||||
*val = !!(ctsts & BIT(1));
|
||||
return 0;
|
||||
case hwmon_temp_crit_alarm:
|
||||
pci_read_config_byte(pdev, REG_CTSTS, &ctsts);
|
||||
*val = !!(ctsts & BIT(0));
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(temp1_input);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp1_crit, thresh, 0xE2);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp1_max_hyst, thresh, 0xEC);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp1_max, thresh, 0xEE);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 0);
|
||||
static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 1);
|
||||
static const struct hwmon_ops i5500_ops = {
|
||||
.is_visible = i5500_is_visible,
|
||||
.read = i5500_read,
|
||||
};
|
||||
|
||||
static struct attribute *i5500_temp_attrs[] = {
|
||||
&dev_attr_temp1_input.attr,
|
||||
&sensor_dev_attr_temp1_crit.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_max.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
|
||||
static const struct hwmon_channel_info *i5500_info[] = {
|
||||
HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ),
|
||||
HWMON_CHANNEL_INFO(temp,
|
||||
HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST | HWMON_T_CRIT |
|
||||
HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM
|
||||
),
|
||||
NULL
|
||||
};
|
||||
|
||||
ATTRIBUTE_GROUPS(i5500_temp);
|
||||
static const struct hwmon_chip_info i5500_chip_info = {
|
||||
.ops = &i5500_ops,
|
||||
.info = i5500_info,
|
||||
};
|
||||
|
||||
static const struct pci_device_id i5500_temp_ids[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x3438) },
|
||||
|
@ -121,9 +130,8 @@ static int i5500_temp_probe(struct pci_dev *pdev,
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev,
|
||||
"intel5500", NULL,
|
||||
i5500_temp_groups);
|
||||
hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev, "intel5500", NULL,
|
||||
&i5500_chip_info, NULL);
|
||||
return PTR_ERR_OR_ZERO(hwmon_dev);
|
||||
}
|
||||
|
||||
|
|
|
@ -127,7 +127,7 @@ struct aem_data {
|
|||
struct device *hwmon_dev;
|
||||
struct platform_device *pdev;
|
||||
struct mutex lock;
|
||||
char valid;
|
||||
bool valid;
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
u8 ver_major;
|
||||
u8 ver_minor;
|
||||
|
|
|
@ -66,7 +66,7 @@ struct ibmpex_bmc_data {
|
|||
struct device *hwmon_dev;
|
||||
struct device *bmc_device;
|
||||
struct mutex lock;
|
||||
char valid;
|
||||
bool valid;
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
|
||||
struct ipmi_addr address;
|
||||
|
@ -239,7 +239,7 @@ static void ibmpex_update_device(struct ibmpex_bmc_data *data)
|
|||
}
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
|
||||
out:
|
||||
mutex_unlock(&data->lock);
|
||||
|
|
|
@ -519,7 +519,7 @@ struct it87_data {
|
|||
unsigned short addr;
|
||||
const char *name;
|
||||
struct mutex update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
bool valid; /* true if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
|
||||
u16 in_scaled; /* Internal voltage sensors are scaled */
|
||||
|
@ -844,7 +844,7 @@ static struct it87_data *it87_update_device(struct device *dev)
|
|||
data->vid &= 0x3f;
|
||||
}
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
@ -980,7 +980,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *attr,
|
|||
regval |= 0x80;
|
||||
it87_write_value(data, IT87_REG_BEEP_ENABLE, regval);
|
||||
}
|
||||
data->valid = 0;
|
||||
data->valid = false;
|
||||
reg = IT87_REG_TEMP_OFFSET[nr];
|
||||
break;
|
||||
}
|
||||
|
@ -1079,7 +1079,7 @@ static ssize_t set_temp_type(struct device *dev, struct device_attribute *attr,
|
|||
it87_write_value(data, IT87_REG_TEMP_ENABLE, data->sensor);
|
||||
if (has_temp_old_peci(data, nr))
|
||||
it87_write_value(data, IT87_REG_TEMP_EXTRA, data->extra);
|
||||
data->valid = 0; /* Force cache refresh */
|
||||
data->valid = false; /* Force cache refresh */
|
||||
mutex_unlock(&data->update_lock);
|
||||
return count;
|
||||
}
|
||||
|
@ -1834,7 +1834,7 @@ static ssize_t clear_intrusion(struct device *dev,
|
|||
config |= BIT(5);
|
||||
it87_write_value(data, IT87_REG_CONFIG, config);
|
||||
/* Invalidate cache to force re-read */
|
||||
data->valid = 0;
|
||||
data->valid = false;
|
||||
}
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
|
@ -3229,7 +3229,7 @@ static int __maybe_unused it87_resume(struct device *dev)
|
|||
it87_start_monitoring(data);
|
||||
|
||||
/* force update */
|
||||
data->valid = 0;
|
||||
data->valid = false;
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
|
|
|
@ -191,7 +191,7 @@ static struct pem_data *pem_update_device(struct device *dev)
|
|||
i2c_smbus_write_byte(client, PEM_CLEAR_INFO_FLAGS);
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
abort:
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -139,7 +139,7 @@ struct lm63_data {
|
|||
struct i2c_client *client;
|
||||
struct mutex update_lock;
|
||||
const struct attribute_group *groups[5];
|
||||
char valid; /* zero until following fields are valid */
|
||||
bool valid; /* false until following fields are valid */
|
||||
char lut_valid; /* zero until lut fields are valid */
|
||||
unsigned long last_updated; /* in jiffies */
|
||||
unsigned long lut_last_updated; /* in jiffies */
|
||||
|
@ -289,7 +289,7 @@ static struct lm63_data *lm63_update_device(struct device *dev)
|
|||
LM63_REG_ALERT_STATUS) & 0x7F;
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
lm63_update_lut(data);
|
||||
|
@ -714,7 +714,7 @@ static ssize_t temp2_type_store(struct device *dev,
|
|||
reg = i2c_smbus_read_byte_data(client, LM96163_REG_TRUTHERM) & ~0x02;
|
||||
i2c_smbus_write_byte_data(client, LM96163_REG_TRUTHERM,
|
||||
reg | (data->trutherm ? 0x02 : 0x00));
|
||||
data->valid = 0;
|
||||
data->valid = false;
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
return count;
|
||||
|
|
|
@ -55,7 +55,7 @@ static const u8 temp_regs[t_num_temp] = {
|
|||
struct lm77_data {
|
||||
struct i2c_client *client;
|
||||
struct mutex update_lock;
|
||||
char valid;
|
||||
bool valid;
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
int temp[t_num_temp]; /* index using temp_index */
|
||||
u8 alarms;
|
||||
|
@ -118,7 +118,7 @@ static struct lm77_data *lm77_update_device(struct device *dev)
|
|||
data->alarms =
|
||||
lm77_read_value(client, LM77_REG_TEMP) & 0x0007;
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -117,7 +117,7 @@ struct lm78_data {
|
|||
int isa_addr;
|
||||
|
||||
struct mutex update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
bool valid; /* true if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
|
||||
u8 in[7]; /* Register value */
|
||||
|
@ -772,7 +772,7 @@ static struct lm78_data *lm78_update_device(struct device *dev)
|
|||
data->alarms = lm78_read_value(data, LM78_REG_ALARM1) +
|
||||
(lm78_read_value(data, LM78_REG_ALARM2) << 8);
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
|
||||
data->fan_div[2] = 1;
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@ struct lm80_data {
|
|||
struct i2c_client *client;
|
||||
struct mutex update_lock;
|
||||
char error; /* !=0 if error occurred during last update */
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
bool valid; /* true if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
|
||||
u8 in[i_num_in][7]; /* Register value, 1st index is enum in_index */
|
||||
|
@ -236,14 +236,14 @@ static struct lm80_data *lm80_update_device(struct device *dev)
|
|||
data->alarms = prev_rv + (rv << 8);
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
data->error = 0;
|
||||
}
|
||||
goto done;
|
||||
|
||||
abort:
|
||||
ret = ERR_PTR(rv);
|
||||
data->valid = 0;
|
||||
data->valid = false;
|
||||
data->error = 1;
|
||||
|
||||
done:
|
||||
|
|
|
@ -105,7 +105,7 @@ struct lm83_data {
|
|||
struct i2c_client *client;
|
||||
const struct attribute_group *groups[3];
|
||||
struct mutex update_lock;
|
||||
char valid; /* zero until following fields are valid */
|
||||
bool valid; /* false until following fields are valid */
|
||||
unsigned long last_updated; /* in jiffies */
|
||||
|
||||
/* registers values */
|
||||
|
@ -137,7 +137,7 @@ static struct lm83_data *lm83_update_device(struct device *dev)
|
|||
<< 8);
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -294,7 +294,7 @@ struct lm85_data {
|
|||
bool has_vid5; /* true if VID5 is configured for ADT7463 or ADT7468 */
|
||||
|
||||
struct mutex update_lock;
|
||||
int valid; /* !=0 if following fields are valid */
|
||||
bool valid; /* true if following fields are valid */
|
||||
unsigned long last_reading; /* In jiffies */
|
||||
unsigned long last_config; /* In jiffies */
|
||||
|
||||
|
@ -541,7 +541,7 @@ static struct lm85_data *lm85_update_device(struct device *dev)
|
|||
data->last_config = jiffies;
|
||||
} /* last_config */
|
||||
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
|
|
|
@ -141,7 +141,7 @@ static u8 LM87_REG_TEMP_LOW[3] = { 0x3A, 0x38, 0x2C };
|
|||
|
||||
struct lm87_data {
|
||||
struct mutex update_lock;
|
||||
char valid; /* zero until following fields are valid */
|
||||
bool valid; /* false until following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
|
||||
u8 channel; /* register value */
|
||||
|
@ -251,7 +251,7 @@ static struct lm87_data *lm87_update_device(struct device *dev)
|
|||
data->aout = lm87_read_value(client, LM87_REG_AOUT);
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -69,10 +69,10 @@
|
|||
* This driver also supports the G781 from GMT. This device is compatible
|
||||
* with the ADM1032.
|
||||
*
|
||||
* This driver also supports TMP451 from Texas Instruments. This device is
|
||||
* supported in both compatibility and extended mode. It's mostly compatible
|
||||
* with ADT7461 except for local temperature low byte register and max
|
||||
* conversion rate.
|
||||
* This driver also supports TMP451 and TMP461 from Texas Instruments.
|
||||
* Those devices are supported in both compatibility and extended mode.
|
||||
* They are mostly compatible with ADT7461 except for local temperature
|
||||
* low byte register and max conversion rate.
|
||||
*
|
||||
* Since the LM90 was the first chipset supported by this driver, most
|
||||
* comments will refer to this chipset, but are actually general and
|
||||
|
@ -112,7 +112,7 @@ static const unsigned short normal_i2c[] = {
|
|||
0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
|
||||
|
||||
enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680,
|
||||
max6646, w83l771, max6696, sa56004, g781, tmp451, max6654 };
|
||||
max6646, w83l771, max6696, sa56004, g781, tmp451, tmp461, max6654 };
|
||||
|
||||
/*
|
||||
* The LM90 registers
|
||||
|
@ -168,8 +168,12 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680,
|
|||
|
||||
#define LM90_MAX_CONVRATE_MS 16000 /* Maximum conversion rate in ms */
|
||||
|
||||
/* TMP451 registers */
|
||||
/* TMP451/TMP461 registers */
|
||||
#define TMP451_REG_R_LOCAL_TEMPL 0x15
|
||||
#define TMP451_REG_CONALERT 0x22
|
||||
|
||||
#define TMP461_REG_CHEN 0x16
|
||||
#define TMP461_REG_DFC 0x24
|
||||
|
||||
/*
|
||||
* Device flags
|
||||
|
@ -182,7 +186,8 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680,
|
|||
#define LM90_HAVE_EMERGENCY_ALARM (1 << 5)/* emergency alarm */
|
||||
#define LM90_HAVE_TEMP3 (1 << 6) /* 3rd temperature sensor */
|
||||
#define LM90_HAVE_BROKEN_ALERT (1 << 7) /* Broken alert */
|
||||
#define LM90_PAUSE_FOR_CONFIG (1 << 8) /* Pause conversion for config */
|
||||
#define LM90_HAVE_EXTENDED_TEMP (1 << 8) /* extended temperature support*/
|
||||
#define LM90_PAUSE_FOR_CONFIG (1 << 9) /* Pause conversion for config */
|
||||
|
||||
/* LM90 status */
|
||||
#define LM90_STATUS_LTHRM (1 << 0) /* local THERM limit tripped */
|
||||
|
@ -229,6 +234,7 @@ static const struct i2c_device_id lm90_id[] = {
|
|||
{ "w83l771", w83l771 },
|
||||
{ "sa56004", sa56004 },
|
||||
{ "tmp451", tmp451 },
|
||||
{ "tmp461", tmp461 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, lm90_id);
|
||||
|
@ -326,6 +332,10 @@ static const struct of_device_id __maybe_unused lm90_of_match[] = {
|
|||
.compatible = "ti,tmp451",
|
||||
.data = (void *)tmp451
|
||||
},
|
||||
{
|
||||
.compatible = "ti,tmp461",
|
||||
.data = (void *)tmp461
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lm90_of_match);
|
||||
|
@ -350,7 +360,7 @@ static const struct lm90_params lm90_params[] = {
|
|||
},
|
||||
[adt7461] = {
|
||||
.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
|
||||
| LM90_HAVE_BROKEN_ALERT,
|
||||
| LM90_HAVE_BROKEN_ALERT | LM90_HAVE_EXTENDED_TEMP,
|
||||
.alert_alarms = 0x7c,
|
||||
.max_convrate = 10,
|
||||
},
|
||||
|
@ -422,7 +432,14 @@ static const struct lm90_params lm90_params[] = {
|
|||
},
|
||||
[tmp451] = {
|
||||
.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
|
||||
| LM90_HAVE_BROKEN_ALERT,
|
||||
| LM90_HAVE_BROKEN_ALERT | LM90_HAVE_EXTENDED_TEMP,
|
||||
.alert_alarms = 0x7c,
|
||||
.max_convrate = 9,
|
||||
.reg_local_ext = TMP451_REG_R_LOCAL_TEMPL,
|
||||
},
|
||||
[tmp461] = {
|
||||
.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
|
||||
| LM90_HAVE_BROKEN_ALERT | LM90_HAVE_EXTENDED_TEMP,
|
||||
.alert_alarms = 0x7c,
|
||||
.max_convrate = 9,
|
||||
.reg_local_ext = TMP451_REG_R_LOCAL_TEMPL,
|
||||
|
@ -998,7 +1015,7 @@ static int lm90_get_temp11(struct lm90_data *data, int index)
|
|||
s16 temp11 = data->temp11[index];
|
||||
int temp;
|
||||
|
||||
if (data->kind == adt7461 || data->kind == tmp451)
|
||||
if (data->flags & LM90_HAVE_EXTENDED_TEMP)
|
||||
temp = temp_from_u16_adt7461(data, temp11);
|
||||
else if (data->kind == max6646)
|
||||
temp = temp_from_u16(temp11);
|
||||
|
@ -1035,7 +1052,7 @@ static int lm90_set_temp11(struct lm90_data *data, int index, long val)
|
|||
val -= 16000;
|
||||
}
|
||||
|
||||
if (data->kind == adt7461 || data->kind == tmp451)
|
||||
if (data->flags & LM90_HAVE_EXTENDED_TEMP)
|
||||
data->temp11[index] = temp_to_u16_adt7461(data, val);
|
||||
else if (data->kind == max6646)
|
||||
data->temp11[index] = temp_to_u8(val) << 8;
|
||||
|
@ -1062,7 +1079,7 @@ static int lm90_get_temp8(struct lm90_data *data, int index)
|
|||
s8 temp8 = data->temp8[index];
|
||||
int temp;
|
||||
|
||||
if (data->kind == adt7461 || data->kind == tmp451)
|
||||
if (data->flags & LM90_HAVE_EXTENDED_TEMP)
|
||||
temp = temp_from_u8_adt7461(data, temp8);
|
||||
else if (data->kind == max6646)
|
||||
temp = temp_from_u8(temp8);
|
||||
|
@ -1098,7 +1115,7 @@ static int lm90_set_temp8(struct lm90_data *data, int index, long val)
|
|||
val -= 16000;
|
||||
}
|
||||
|
||||
if (data->kind == adt7461 || data->kind == tmp451)
|
||||
if (data->flags & LM90_HAVE_EXTENDED_TEMP)
|
||||
data->temp8[index] = temp_to_u8_adt7461(data, val);
|
||||
else if (data->kind == max6646)
|
||||
data->temp8[index] = temp_to_u8(val);
|
||||
|
@ -1116,7 +1133,7 @@ static int lm90_get_temphyst(struct lm90_data *data, int index)
|
|||
{
|
||||
int temp;
|
||||
|
||||
if (data->kind == adt7461 || data->kind == tmp451)
|
||||
if (data->flags & LM90_HAVE_EXTENDED_TEMP)
|
||||
temp = temp_from_u8_adt7461(data, data->temp8[index]);
|
||||
else if (data->kind == max6646)
|
||||
temp = temp_from_u8(data->temp8[index]);
|
||||
|
@ -1136,7 +1153,7 @@ static int lm90_set_temphyst(struct lm90_data *data, long val)
|
|||
int temp;
|
||||
int err;
|
||||
|
||||
if (data->kind == adt7461 || data->kind == tmp451)
|
||||
if (data->flags & LM90_HAVE_EXTENDED_TEMP)
|
||||
temp = temp_from_u8_adt7461(data, data->temp8[LOCAL_CRIT]);
|
||||
else if (data->kind == max6646)
|
||||
temp = temp_from_u8(data->temp8[LOCAL_CRIT]);
|
||||
|
@ -1627,18 +1644,26 @@ static int lm90_detect(struct i2c_client *client,
|
|||
&& convrate <= 0x08)
|
||||
name = "g781";
|
||||
} else
|
||||
if (address == 0x4C
|
||||
&& man_id == 0x55) { /* Texas Instruments */
|
||||
int local_ext;
|
||||
if (man_id == 0x55 && chip_id == 0x00 &&
|
||||
(config1 & 0x1B) == 0x00 && convrate <= 0x09) {
|
||||
int local_ext, conalert, chen, dfc;
|
||||
|
||||
local_ext = i2c_smbus_read_byte_data(client,
|
||||
TMP451_REG_R_LOCAL_TEMPL);
|
||||
conalert = i2c_smbus_read_byte_data(client,
|
||||
TMP451_REG_CONALERT);
|
||||
chen = i2c_smbus_read_byte_data(client, TMP461_REG_CHEN);
|
||||
dfc = i2c_smbus_read_byte_data(client, TMP461_REG_DFC);
|
||||
|
||||
if (chip_id == 0x00 /* TMP451 */
|
||||
&& (config1 & 0x1B) == 0x00
|
||||
&& convrate <= 0x09
|
||||
&& (local_ext & 0x0F) == 0x00)
|
||||
name = "tmp451";
|
||||
if ((local_ext & 0x0F) == 0x00 &&
|
||||
(conalert & 0xf1) == 0x01 &&
|
||||
(chen & 0xfc) == 0x00 &&
|
||||
(dfc & 0xfc) == 0x00) {
|
||||
if (address == 0x4c && !(chen & 0x03))
|
||||
name = "tmp451";
|
||||
else if (address >= 0x48 && address <= 0x4f)
|
||||
name = "tmp461";
|
||||
}
|
||||
}
|
||||
|
||||
if (!name) { /* identification failed */
|
||||
|
@ -1685,7 +1710,7 @@ static int lm90_init_client(struct i2c_client *client, struct lm90_data *data)
|
|||
lm90_set_convrate(client, data, 500); /* 500ms; 2Hz conversion rate */
|
||||
|
||||
/* Check Temperature Range Select */
|
||||
if (data->kind == adt7461 || data->kind == tmp451) {
|
||||
if (data->flags & LM90_HAVE_EXTENDED_TEMP) {
|
||||
if (config & 0x04)
|
||||
data->flags |= LM90_FLAG_ADT7461_EXT;
|
||||
}
|
||||
|
|
|
@ -99,7 +99,7 @@ static const u8 regs[t_num_regs] = {
|
|||
struct lm92_data {
|
||||
struct i2c_client *client;
|
||||
struct mutex update_lock;
|
||||
char valid; /* zero until following fields are valid */
|
||||
bool valid; /* false until following fields are valid */
|
||||
unsigned long last_updated; /* in jiffies */
|
||||
|
||||
/* registers values */
|
||||
|
@ -126,7 +126,7 @@ static struct lm92_data *lm92_update_device(struct device *dev)
|
|||
i2c_smbus_read_word_swapped(client, regs[i]);
|
||||
}
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -202,7 +202,7 @@ struct lm93_data {
|
|||
/* client update function */
|
||||
void (*update)(struct lm93_data *, struct i2c_client *);
|
||||
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
bool valid; /* true if following fields are valid */
|
||||
|
||||
/* register values, arranged by block read groups */
|
||||
struct block1_t block1;
|
||||
|
@ -917,7 +917,7 @@ static struct lm93_data *lm93_update_device(struct device *dev)
|
|||
|
||||
data->update(data, client);
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -78,7 +78,7 @@ struct lm95241_data {
|
|||
struct mutex update_lock;
|
||||
unsigned long last_updated; /* in jiffies */
|
||||
unsigned long interval; /* in milli-seconds */
|
||||
char valid; /* zero until following fields are valid */
|
||||
bool valid; /* false until following fields are valid */
|
||||
/* registers values */
|
||||
u8 temp[ARRAY_SIZE(lm95241_reg_address)];
|
||||
u8 status, config, model, trutherm;
|
||||
|
@ -118,7 +118,7 @@ static struct lm95241_data *lm95241_update_device(struct device *dev)
|
|||
data->status = i2c_smbus_read_byte_data(client,
|
||||
LM95241_REG_R_STATUS);
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
@ -257,7 +257,7 @@ static int lm95241_write_temp(struct device *dev, u32 attr, int channel,
|
|||
else
|
||||
data->config &= ~R2DF_MASK;
|
||||
}
|
||||
data->valid = 0;
|
||||
data->valid = false;
|
||||
ret = i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG,
|
||||
data->config);
|
||||
break;
|
||||
|
@ -273,7 +273,7 @@ static int lm95241_write_temp(struct device *dev, u32 attr, int channel,
|
|||
else
|
||||
data->config &= ~R2DF_MASK;
|
||||
}
|
||||
data->valid = 0;
|
||||
data->valid = false;
|
||||
ret = i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG,
|
||||
data->config);
|
||||
break;
|
||||
|
|
|
@ -77,7 +77,7 @@ static struct ltc4151_data *ltc4151_update_device(struct device *dev)
|
|||
data->regs[i] = val;
|
||||
}
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
abort:
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -64,7 +64,7 @@ static struct ltc4215_data *ltc4215_update_device(struct device *dev)
|
|||
}
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -73,13 +73,13 @@ static struct ltc4261_data *ltc4261_update_device(struct device *dev)
|
|||
"Failed to read ADC value: error %d\n",
|
||||
val);
|
||||
ret = ERR_PTR(val);
|
||||
data->valid = 0;
|
||||
data->valid = false;
|
||||
goto abort;
|
||||
}
|
||||
data->regs[i] = val;
|
||||
}
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
abort:
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -166,7 +166,7 @@ static struct max16065_data *max16065_update_device(struct device *dev)
|
|||
= i2c_smbus_read_byte_data(client, MAX16065_FAULT(i));
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
mutex_unlock(&data->update_lock);
|
||||
return data;
|
||||
|
|
|
@ -79,7 +79,7 @@ enum temp_index {
|
|||
struct max1619_data {
|
||||
struct i2c_client *client;
|
||||
struct mutex update_lock;
|
||||
char valid; /* zero until following fields are valid */
|
||||
bool valid; /* false until following fields are valid */
|
||||
unsigned long last_updated; /* in jiffies */
|
||||
|
||||
/* registers values */
|
||||
|
@ -124,7 +124,7 @@ static struct max1619_data *max1619_update_device(struct device *dev)
|
|||
data->alarms ^= 0x02;
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -58,7 +58,7 @@ struct max1668_data {
|
|||
enum chips type;
|
||||
|
||||
struct mutex update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
bool valid; /* true if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
|
||||
/* 1x local and 4x remote */
|
||||
|
@ -120,7 +120,7 @@ static struct max1668_data *max1668_update_device(struct device *dev)
|
|||
data->alarms |= val;
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
abort:
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
|
|
|
@ -103,10 +103,16 @@ static int max31722_probe(struct spi_device *spi)
|
|||
static int max31722_remove(struct spi_device *spi)
|
||||
{
|
||||
struct max31722_data *data = spi_get_drvdata(spi);
|
||||
int ret;
|
||||
|
||||
hwmon_device_unregister(data->hwmon_dev);
|
||||
|
||||
return max31722_set_mode(data, MAX31722_MODE_STANDBY);
|
||||
ret = max31722_set_mode(data, MAX31722_MODE_STANDBY);
|
||||
if (ret)
|
||||
/* There is nothing we can do about this ... */
|
||||
dev_warn(&spi->dev, "Failed to put device in stand-by mode\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused max31722_suspend(struct device *dev)
|
||||
|
|
|
@ -0,0 +1,514 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Hardware monitoring driver for Maxim MAX6620
|
||||
*
|
||||
* Originally from L. Grunenberg.
|
||||
* (C) 2012 by L. Grunenberg <contact@lgrunenberg.de>
|
||||
*
|
||||
* Copyright (c) 2021 Dell Inc. or its subsidiaries. All Rights Reserved.
|
||||
*
|
||||
* based on code written by :
|
||||
* 2007 by Hans J. Koch <hjk@hansjkoch.de>
|
||||
* John Morris <john.morris@spirentcom.com>
|
||||
* Copyright (c) 2003 Spirent Communications
|
||||
* and Claus Gindhart <claus.gindhart@kontron.com>
|
||||
*
|
||||
* This module has only been tested with the MAX6620 chip.
|
||||
*
|
||||
* The datasheet was last seen at:
|
||||
*
|
||||
* http://pdfserv.maxim-ic.com/en/ds/MAX6620.pdf
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
/*
|
||||
* MAX 6620 registers
|
||||
*/
|
||||
|
||||
#define MAX6620_REG_CONFIG 0x00
|
||||
#define MAX6620_REG_FAULT 0x01
|
||||
#define MAX6620_REG_CONF_FAN0 0x02
|
||||
#define MAX6620_REG_CONF_FAN1 0x03
|
||||
#define MAX6620_REG_CONF_FAN2 0x04
|
||||
#define MAX6620_REG_CONF_FAN3 0x05
|
||||
#define MAX6620_REG_DYN_FAN0 0x06
|
||||
#define MAX6620_REG_DYN_FAN1 0x07
|
||||
#define MAX6620_REG_DYN_FAN2 0x08
|
||||
#define MAX6620_REG_DYN_FAN3 0x09
|
||||
#define MAX6620_REG_TACH0 0x10
|
||||
#define MAX6620_REG_TACH1 0x12
|
||||
#define MAX6620_REG_TACH2 0x14
|
||||
#define MAX6620_REG_TACH3 0x16
|
||||
#define MAX6620_REG_VOLT0 0x18
|
||||
#define MAX6620_REG_VOLT1 0x1A
|
||||
#define MAX6620_REG_VOLT2 0x1C
|
||||
#define MAX6620_REG_VOLT3 0x1E
|
||||
#define MAX6620_REG_TAR0 0x20
|
||||
#define MAX6620_REG_TAR1 0x22
|
||||
#define MAX6620_REG_TAR2 0x24
|
||||
#define MAX6620_REG_TAR3 0x26
|
||||
#define MAX6620_REG_DAC0 0x28
|
||||
#define MAX6620_REG_DAC1 0x2A
|
||||
#define MAX6620_REG_DAC2 0x2C
|
||||
#define MAX6620_REG_DAC3 0x2E
|
||||
|
||||
/*
|
||||
* Config register bits
|
||||
*/
|
||||
|
||||
#define MAX6620_CFG_RUN BIT(7)
|
||||
#define MAX6620_CFG_POR BIT(6)
|
||||
#define MAX6620_CFG_TIMEOUT BIT(5)
|
||||
#define MAX6620_CFG_FULLFAN BIT(4)
|
||||
#define MAX6620_CFG_OSC BIT(3)
|
||||
#define MAX6620_CFG_WD_MASK (BIT(2) | BIT(1))
|
||||
#define MAX6620_CFG_WD_2 BIT(1)
|
||||
#define MAX6620_CFG_WD_6 BIT(2)
|
||||
#define MAX6620_CFG_WD10 (BIT(2) | BIT(1))
|
||||
#define MAX6620_CFG_WD BIT(0)
|
||||
|
||||
/*
|
||||
* Failure status register bits
|
||||
*/
|
||||
|
||||
#define MAX6620_FAIL_TACH0 BIT(4)
|
||||
#define MAX6620_FAIL_TACH1 BIT(5)
|
||||
#define MAX6620_FAIL_TACH2 BIT(6)
|
||||
#define MAX6620_FAIL_TACH3 BIT(7)
|
||||
#define MAX6620_FAIL_MASK0 BIT(0)
|
||||
#define MAX6620_FAIL_MASK1 BIT(1)
|
||||
#define MAX6620_FAIL_MASK2 BIT(2)
|
||||
#define MAX6620_FAIL_MASK3 BIT(3)
|
||||
|
||||
#define MAX6620_CLOCK_FREQ 8192 /* Clock frequency in Hz */
|
||||
#define MAX6620_PULSE_PER_REV 2 /* Tachometer pulses per revolution */
|
||||
|
||||
/* Minimum and maximum values of the FAN-RPM */
|
||||
#define FAN_RPM_MIN 240
|
||||
#define FAN_RPM_MAX 30000
|
||||
|
||||
static const u8 config_reg[] = {
|
||||
MAX6620_REG_CONF_FAN0,
|
||||
MAX6620_REG_CONF_FAN1,
|
||||
MAX6620_REG_CONF_FAN2,
|
||||
MAX6620_REG_CONF_FAN3,
|
||||
};
|
||||
|
||||
static const u8 dyn_reg[] = {
|
||||
MAX6620_REG_DYN_FAN0,
|
||||
MAX6620_REG_DYN_FAN1,
|
||||
MAX6620_REG_DYN_FAN2,
|
||||
MAX6620_REG_DYN_FAN3,
|
||||
};
|
||||
|
||||
static const u8 tach_reg[] = {
|
||||
MAX6620_REG_TACH0,
|
||||
MAX6620_REG_TACH1,
|
||||
MAX6620_REG_TACH2,
|
||||
MAX6620_REG_TACH3,
|
||||
};
|
||||
|
||||
static const u8 target_reg[] = {
|
||||
MAX6620_REG_TAR0,
|
||||
MAX6620_REG_TAR1,
|
||||
MAX6620_REG_TAR2,
|
||||
MAX6620_REG_TAR3,
|
||||
};
|
||||
|
||||
/*
|
||||
* Client data (each client gets its own)
|
||||
*/
|
||||
|
||||
struct max6620_data {
|
||||
struct i2c_client *client;
|
||||
struct mutex update_lock;
|
||||
bool valid; /* false until following fields are valid */
|
||||
unsigned long last_updated; /* in jiffies */
|
||||
|
||||
/* register values */
|
||||
u8 fancfg[4];
|
||||
u8 fandyn[4];
|
||||
u8 fault;
|
||||
u16 tach[4];
|
||||
u16 target[4];
|
||||
};
|
||||
|
||||
static u8 max6620_fan_div_from_reg(u8 val)
|
||||
{
|
||||
return BIT((val & 0xE0) >> 5);
|
||||
}
|
||||
|
||||
static u16 max6620_fan_rpm_to_tach(u8 div, int rpm)
|
||||
{
|
||||
return (60 * div * MAX6620_CLOCK_FREQ) / (rpm * MAX6620_PULSE_PER_REV);
|
||||
}
|
||||
|
||||
static int max6620_fan_tach_to_rpm(u8 div, u16 tach)
|
||||
{
|
||||
return (60 * div * MAX6620_CLOCK_FREQ) / (tach * MAX6620_PULSE_PER_REV);
|
||||
}
|
||||
|
||||
static int max6620_update_device(struct device *dev)
|
||||
{
|
||||
struct max6620_data *data = dev_get_drvdata(dev);
|
||||
struct i2c_client *client = data->client;
|
||||
int i;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
|
||||
if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
ret = i2c_smbus_read_byte_data(client, config_reg[i]);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
data->fancfg[i] = ret;
|
||||
|
||||
ret = i2c_smbus_read_byte_data(client, dyn_reg[i]);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
data->fandyn[i] = ret;
|
||||
|
||||
ret = i2c_smbus_read_byte_data(client, tach_reg[i]);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
data->tach[i] = (ret << 3) & 0x7f8;
|
||||
ret = i2c_smbus_read_byte_data(client, tach_reg[i] + 1);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
data->tach[i] |= (ret >> 5) & 0x7;
|
||||
|
||||
ret = i2c_smbus_read_byte_data(client, target_reg[i]);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
data->target[i] = (ret << 3) & 0x7f8;
|
||||
ret = i2c_smbus_read_byte_data(client, target_reg[i] + 1);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
data->target[i] |= (ret >> 5) & 0x7;
|
||||
}
|
||||
|
||||
/*
|
||||
* Alarms are cleared on read in case the condition that
|
||||
* caused the alarm is removed. Keep the value latched here
|
||||
* for providing the register through different alarm files.
|
||||
*/
|
||||
ret = i2c_smbus_read_byte_data(client, MAX6620_REG_FAULT);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
data->fault |= (ret >> 4) & (ret & 0x0F);
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
error:
|
||||
mutex_unlock(&data->update_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static umode_t
|
||||
max6620_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr,
|
||||
int channel)
|
||||
{
|
||||
switch (type) {
|
||||
case hwmon_fan:
|
||||
switch (attr) {
|
||||
case hwmon_fan_alarm:
|
||||
case hwmon_fan_input:
|
||||
return 0444;
|
||||
case hwmon_fan_div:
|
||||
case hwmon_fan_target:
|
||||
return 0644;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
max6620_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
|
||||
int channel, long *val)
|
||||
{
|
||||
struct max6620_data *data;
|
||||
struct i2c_client *client;
|
||||
int ret;
|
||||
u8 div;
|
||||
u8 val1;
|
||||
u8 val2;
|
||||
|
||||
ret = max6620_update_device(dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
data = dev_get_drvdata(dev);
|
||||
client = data->client;
|
||||
|
||||
switch (type) {
|
||||
case hwmon_fan:
|
||||
switch (attr) {
|
||||
case hwmon_fan_alarm:
|
||||
mutex_lock(&data->update_lock);
|
||||
*val = !!(data->fault & BIT(channel));
|
||||
|
||||
/* Setting TACH count to re-enable fan fault detection */
|
||||
if (*val == 1) {
|
||||
val1 = (data->target[channel] >> 3) & 0xff;
|
||||
val2 = (data->target[channel] << 5) & 0xe0;
|
||||
ret = i2c_smbus_write_byte_data(client,
|
||||
target_reg[channel], val1);
|
||||
if (ret < 0) {
|
||||
mutex_unlock(&data->update_lock);
|
||||
return ret;
|
||||
}
|
||||
ret = i2c_smbus_write_byte_data(client,
|
||||
target_reg[channel] + 1, val2);
|
||||
if (ret < 0) {
|
||||
mutex_unlock(&data->update_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
data->fault &= ~BIT(channel);
|
||||
}
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
break;
|
||||
case hwmon_fan_div:
|
||||
*val = max6620_fan_div_from_reg(data->fandyn[channel]);
|
||||
break;
|
||||
case hwmon_fan_input:
|
||||
if (data->tach[channel] == 0) {
|
||||
*val = 0;
|
||||
} else {
|
||||
div = max6620_fan_div_from_reg(data->fandyn[channel]);
|
||||
*val = max6620_fan_tach_to_rpm(div, data->tach[channel]);
|
||||
}
|
||||
break;
|
||||
case hwmon_fan_target:
|
||||
if (data->target[channel] == 0) {
|
||||
*val = 0;
|
||||
} else {
|
||||
div = max6620_fan_div_from_reg(data->fandyn[channel]);
|
||||
*val = max6620_fan_tach_to_rpm(div, data->target[channel]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
max6620_write(struct device *dev, enum hwmon_sensor_types type, u32 attr,
|
||||
int channel, long val)
|
||||
{
|
||||
struct max6620_data *data;
|
||||
struct i2c_client *client;
|
||||
int ret;
|
||||
u8 div;
|
||||
u16 tach;
|
||||
u8 val1;
|
||||
u8 val2;
|
||||
|
||||
ret = max6620_update_device(dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
data = dev_get_drvdata(dev);
|
||||
client = data->client;
|
||||
mutex_lock(&data->update_lock);
|
||||
|
||||
switch (type) {
|
||||
case hwmon_fan:
|
||||
switch (attr) {
|
||||
case hwmon_fan_div:
|
||||
switch (val) {
|
||||
case 1:
|
||||
div = 0;
|
||||
break;
|
||||
case 2:
|
||||
div = 1;
|
||||
break;
|
||||
case 4:
|
||||
div = 2;
|
||||
break;
|
||||
case 8:
|
||||
div = 3;
|
||||
break;
|
||||
case 16:
|
||||
div = 4;
|
||||
break;
|
||||
case 32:
|
||||
div = 5;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
data->fandyn[channel] &= 0x1F;
|
||||
data->fandyn[channel] |= div << 5;
|
||||
ret = i2c_smbus_write_byte_data(client, dyn_reg[channel],
|
||||
data->fandyn[channel]);
|
||||
break;
|
||||
case hwmon_fan_target:
|
||||
val = clamp_val(val, FAN_RPM_MIN, FAN_RPM_MAX);
|
||||
div = max6620_fan_div_from_reg(data->fandyn[channel]);
|
||||
tach = max6620_fan_rpm_to_tach(div, val);
|
||||
val1 = (tach >> 3) & 0xff;
|
||||
val2 = (tach << 5) & 0xe0;
|
||||
ret = i2c_smbus_write_byte_data(client, target_reg[channel], val1);
|
||||
if (ret < 0)
|
||||
break;
|
||||
ret = i2c_smbus_write_byte_data(client, target_reg[channel] + 1, val2);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
/* Setting TACH count re-enables fan fault detection */
|
||||
data->fault &= ~BIT(channel);
|
||||
|
||||
break;
|
||||
default:
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
error:
|
||||
mutex_unlock(&data->update_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct hwmon_channel_info *max6620_info[] = {
|
||||
HWMON_CHANNEL_INFO(fan,
|
||||
HWMON_F_INPUT | HWMON_F_DIV | HWMON_F_TARGET | HWMON_F_ALARM,
|
||||
HWMON_F_INPUT | HWMON_F_DIV | HWMON_F_TARGET | HWMON_F_ALARM,
|
||||
HWMON_F_INPUT | HWMON_F_DIV | HWMON_F_TARGET | HWMON_F_ALARM,
|
||||
HWMON_F_INPUT | HWMON_F_DIV | HWMON_F_TARGET | HWMON_F_ALARM),
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct hwmon_ops max6620_hwmon_ops = {
|
||||
.read = max6620_read,
|
||||
.write = max6620_write,
|
||||
.is_visible = max6620_is_visible,
|
||||
};
|
||||
|
||||
static const struct hwmon_chip_info max6620_chip_info = {
|
||||
.ops = &max6620_hwmon_ops,
|
||||
.info = max6620_info,
|
||||
};
|
||||
|
||||
static int max6620_init_client(struct max6620_data *data)
|
||||
{
|
||||
struct i2c_client *client = data->client;
|
||||
int config;
|
||||
int err;
|
||||
int i;
|
||||
int reg;
|
||||
|
||||
config = i2c_smbus_read_byte_data(client, MAX6620_REG_CONFIG);
|
||||
if (config < 0) {
|
||||
dev_err(&client->dev, "Error reading config, aborting.\n");
|
||||
return config;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set bit 4, disable other fans from going full speed on a fail
|
||||
* failure.
|
||||
*/
|
||||
err = i2c_smbus_write_byte_data(client, MAX6620_REG_CONFIG, config | 0x10);
|
||||
if (err < 0) {
|
||||
dev_err(&client->dev, "Config write error, aborting.\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
reg = i2c_smbus_read_byte_data(client, config_reg[i]);
|
||||
if (reg < 0)
|
||||
return reg;
|
||||
data->fancfg[i] = reg;
|
||||
|
||||
/* Enable RPM mode */
|
||||
data->fancfg[i] |= 0xa8;
|
||||
err = i2c_smbus_write_byte_data(client, config_reg[i], data->fancfg[i]);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* 2 counts (001) and Rate change 100 (0.125 secs) */
|
||||
data->fandyn[i] = 0x30;
|
||||
err = i2c_smbus_write_byte_data(client, dyn_reg[i], data->fandyn[i]);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max6620_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct max6620_data *data;
|
||||
struct device *hwmon_dev;
|
||||
int err;
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(struct max6620_data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->client = client;
|
||||
mutex_init(&data->update_lock);
|
||||
|
||||
err = max6620_init_client(data);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
|
||||
data,
|
||||
&max6620_chip_info,
|
||||
NULL);
|
||||
|
||||
return PTR_ERR_OR_ZERO(hwmon_dev);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id max6620_id[] = {
|
||||
{ "max6620", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, max6620_id);
|
||||
|
||||
static struct i2c_driver max6620_driver = {
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.driver = {
|
||||
.name = "max6620",
|
||||
},
|
||||
.probe_new = max6620_probe,
|
||||
.id_table = max6620_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(max6620_driver);
|
||||
|
||||
MODULE_AUTHOR("Lucas Grunenberg");
|
||||
MODULE_DESCRIPTION("MAX6620 sensor driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -69,7 +69,7 @@ static const int rpm_ranges[] = { 2000, 4000, 8000, 16000 };
|
|||
struct max6639_data {
|
||||
struct i2c_client *client;
|
||||
struct mutex update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
bool valid; /* true if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
|
||||
/* Register values sampled regularly */
|
||||
|
@ -141,7 +141,7 @@ static struct max6639_data *max6639_update_device(struct device *dev)
|
|||
}
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
abort:
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -181,7 +181,7 @@ static struct max6642_data *max6642_update_device(struct device *dev)
|
|||
MAX6642_REG_R_STATUS);
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -12,7 +12,9 @@
|
|||
#include <linux/regmap.h>
|
||||
#include <linux/thermal.h>
|
||||
|
||||
#define MLXREG_FAN_MAX_TACHO 12
|
||||
#define MLXREG_FAN_MAX_TACHO 14
|
||||
#define MLXREG_FAN_MAX_PWM 4
|
||||
#define MLXREG_FAN_PWM_NOT_CONNECTED 0xff
|
||||
#define MLXREG_FAN_MAX_STATE 10
|
||||
#define MLXREG_FAN_MIN_DUTY 51 /* 20% */
|
||||
#define MLXREG_FAN_MAX_DUTY 255 /* 100% */
|
||||
|
@ -61,6 +63,8 @@
|
|||
MLXREG_FAN_MAX_DUTY, \
|
||||
MLXREG_FAN_MAX_STATE))
|
||||
|
||||
struct mlxreg_fan;
|
||||
|
||||
/*
|
||||
* struct mlxreg_fan_tacho - tachometer data (internal use):
|
||||
*
|
||||
|
@ -79,12 +83,18 @@ struct mlxreg_fan_tacho {
|
|||
/*
|
||||
* struct mlxreg_fan_pwm - PWM data (internal use):
|
||||
*
|
||||
* @fan: private data;
|
||||
* @connected: indicates if PWM is connected;
|
||||
* @reg: register offset;
|
||||
* @cooling: cooling device levels;
|
||||
* @cdev: cooling device;
|
||||
*/
|
||||
struct mlxreg_fan_pwm {
|
||||
struct mlxreg_fan *fan;
|
||||
bool connected;
|
||||
u32 reg;
|
||||
u8 cooling_levels[MLXREG_FAN_MAX_STATE + 1];
|
||||
struct thermal_cooling_device *cdev;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -97,20 +107,16 @@ struct mlxreg_fan_pwm {
|
|||
* @tachos_per_drwr - number of tachometers per drawer;
|
||||
* @samples: minimum allowed samples per pulse;
|
||||
* @divider: divider value for tachometer RPM calculation;
|
||||
* @cooling: cooling device levels;
|
||||
* @cdev: cooling device;
|
||||
*/
|
||||
struct mlxreg_fan {
|
||||
struct device *dev;
|
||||
void *regmap;
|
||||
struct mlxreg_core_platform_data *pdata;
|
||||
struct mlxreg_fan_tacho tacho[MLXREG_FAN_MAX_TACHO];
|
||||
struct mlxreg_fan_pwm pwm;
|
||||
struct mlxreg_fan_pwm pwm[MLXREG_FAN_MAX_PWM];
|
||||
int tachos_per_drwr;
|
||||
int samples;
|
||||
int divider;
|
||||
u8 cooling_levels[MLXREG_FAN_MAX_STATE + 1];
|
||||
struct thermal_cooling_device *cdev;
|
||||
};
|
||||
|
||||
static int
|
||||
|
@ -119,6 +125,7 @@ mlxreg_fan_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
|
|||
{
|
||||
struct mlxreg_fan *fan = dev_get_drvdata(dev);
|
||||
struct mlxreg_fan_tacho *tacho;
|
||||
struct mlxreg_fan_pwm *pwm;
|
||||
u32 regval;
|
||||
int err;
|
||||
|
||||
|
@ -169,9 +176,10 @@ mlxreg_fan_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
|
|||
break;
|
||||
|
||||
case hwmon_pwm:
|
||||
pwm = &fan->pwm[channel];
|
||||
switch (attr) {
|
||||
case hwmon_pwm_input:
|
||||
err = regmap_read(fan->regmap, fan->pwm.reg, ®val);
|
||||
err = regmap_read(fan->regmap, pwm->reg, ®val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -195,6 +203,7 @@ mlxreg_fan_write(struct device *dev, enum hwmon_sensor_types type, u32 attr,
|
|||
int channel, long val)
|
||||
{
|
||||
struct mlxreg_fan *fan = dev_get_drvdata(dev);
|
||||
struct mlxreg_fan_pwm *pwm;
|
||||
|
||||
switch (type) {
|
||||
case hwmon_pwm:
|
||||
|
@ -203,7 +212,8 @@ mlxreg_fan_write(struct device *dev, enum hwmon_sensor_types type, u32 attr,
|
|||
if (val < MLXREG_FAN_MIN_DUTY ||
|
||||
val > MLXREG_FAN_MAX_DUTY)
|
||||
return -EINVAL;
|
||||
return regmap_write(fan->regmap, fan->pwm.reg, val);
|
||||
pwm = &fan->pwm[channel];
|
||||
return regmap_write(fan->regmap, pwm->reg, val);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
@ -235,7 +245,7 @@ mlxreg_fan_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr,
|
|||
break;
|
||||
|
||||
case hwmon_pwm:
|
||||
if (!(((struct mlxreg_fan *)data)->pwm.connected))
|
||||
if (!(((struct mlxreg_fan *)data)->pwm[channel].connected))
|
||||
return 0;
|
||||
|
||||
switch (attr) {
|
||||
|
@ -253,6 +263,13 @@ mlxreg_fan_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static char *mlxreg_fan_name[] = {
|
||||
"mlxreg_fan",
|
||||
"mlxreg_fan1",
|
||||
"mlxreg_fan2",
|
||||
"mlxreg_fan3",
|
||||
};
|
||||
|
||||
static const struct hwmon_channel_info *mlxreg_fan_hwmon_info[] = {
|
||||
HWMON_CHANNEL_INFO(fan,
|
||||
HWMON_F_INPUT | HWMON_F_FAULT,
|
||||
|
@ -266,8 +283,13 @@ static const struct hwmon_channel_info *mlxreg_fan_hwmon_info[] = {
|
|||
HWMON_F_INPUT | HWMON_F_FAULT,
|
||||
HWMON_F_INPUT | HWMON_F_FAULT,
|
||||
HWMON_F_INPUT | HWMON_F_FAULT,
|
||||
HWMON_F_INPUT | HWMON_F_FAULT,
|
||||
HWMON_F_INPUT | HWMON_F_FAULT,
|
||||
HWMON_F_INPUT | HWMON_F_FAULT),
|
||||
HWMON_CHANNEL_INFO(pwm,
|
||||
HWMON_PWM_INPUT,
|
||||
HWMON_PWM_INPUT,
|
||||
HWMON_PWM_INPUT,
|
||||
HWMON_PWM_INPUT),
|
||||
NULL
|
||||
};
|
||||
|
@ -294,11 +316,12 @@ static int mlxreg_fan_get_cur_state(struct thermal_cooling_device *cdev,
|
|||
unsigned long *state)
|
||||
|
||||
{
|
||||
struct mlxreg_fan *fan = cdev->devdata;
|
||||
struct mlxreg_fan_pwm *pwm = cdev->devdata;
|
||||
struct mlxreg_fan *fan = pwm->fan;
|
||||
u32 regval;
|
||||
int err;
|
||||
|
||||
err = regmap_read(fan->regmap, fan->pwm.reg, ®val);
|
||||
err = regmap_read(fan->regmap, pwm->reg, ®val);
|
||||
if (err) {
|
||||
dev_err(fan->dev, "Failed to query PWM duty\n");
|
||||
return err;
|
||||
|
@ -313,7 +336,8 @@ static int mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev,
|
|||
unsigned long state)
|
||||
|
||||
{
|
||||
struct mlxreg_fan *fan = cdev->devdata;
|
||||
struct mlxreg_fan_pwm *pwm = cdev->devdata;
|
||||
struct mlxreg_fan *fan = pwm->fan;
|
||||
unsigned long cur_state;
|
||||
int i, config = 0;
|
||||
u32 regval;
|
||||
|
@ -337,11 +361,11 @@ static int mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev,
|
|||
config = 1;
|
||||
state -= MLXREG_FAN_MAX_STATE;
|
||||
for (i = 0; i < state; i++)
|
||||
fan->cooling_levels[i] = state;
|
||||
pwm->cooling_levels[i] = state;
|
||||
for (i = state; i <= MLXREG_FAN_MAX_STATE; i++)
|
||||
fan->cooling_levels[i] = i;
|
||||
pwm->cooling_levels[i] = i;
|
||||
|
||||
err = regmap_read(fan->regmap, fan->pwm.reg, ®val);
|
||||
err = regmap_read(fan->regmap, pwm->reg, ®val);
|
||||
if (err) {
|
||||
dev_err(fan->dev, "Failed to query PWM duty\n");
|
||||
return err;
|
||||
|
@ -358,8 +382,8 @@ static int mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev,
|
|||
return -EINVAL;
|
||||
|
||||
/* Normalize the state to the valid speed range. */
|
||||
state = fan->cooling_levels[state];
|
||||
err = regmap_write(fan->regmap, fan->pwm.reg,
|
||||
state = pwm->cooling_levels[state];
|
||||
err = regmap_write(fan->regmap, pwm->reg,
|
||||
MLXREG_FAN_PWM_STATE2DUTY(state));
|
||||
if (err) {
|
||||
dev_err(fan->dev, "Failed to write PWM duty\n");
|
||||
|
@ -390,6 +414,22 @@ static int mlxreg_fan_connect_verify(struct mlxreg_fan *fan,
|
|||
return !!(regval & data->bit);
|
||||
}
|
||||
|
||||
static int mlxreg_pwm_connect_verify(struct mlxreg_fan *fan,
|
||||
struct mlxreg_core_data *data)
|
||||
{
|
||||
u32 regval;
|
||||
int err;
|
||||
|
||||
err = regmap_read(fan->regmap, data->reg, ®val);
|
||||
if (err) {
|
||||
dev_err(fan->dev, "Failed to query pwm register 0x%08x\n",
|
||||
data->reg);
|
||||
return err;
|
||||
}
|
||||
|
||||
return regval != MLXREG_FAN_PWM_NOT_CONNECTED;
|
||||
}
|
||||
|
||||
static int mlxreg_fan_speed_divider_get(struct mlxreg_fan *fan,
|
||||
struct mlxreg_core_data *data)
|
||||
{
|
||||
|
@ -418,8 +458,8 @@ static int mlxreg_fan_speed_divider_get(struct mlxreg_fan *fan,
|
|||
static int mlxreg_fan_config(struct mlxreg_fan *fan,
|
||||
struct mlxreg_core_platform_data *pdata)
|
||||
{
|
||||
int tacho_num = 0, tacho_avail = 0, pwm_num = 0, i;
|
||||
struct mlxreg_core_data *data = pdata->data;
|
||||
int tacho_num = 0, tacho_avail = 0, i;
|
||||
bool configured = false;
|
||||
int err;
|
||||
|
||||
|
@ -449,13 +489,24 @@ static int mlxreg_fan_config(struct mlxreg_fan *fan,
|
|||
fan->tacho[tacho_num++].connected = true;
|
||||
tacho_avail++;
|
||||
} else if (strnstr(data->label, "pwm", sizeof(data->label))) {
|
||||
if (fan->pwm.connected) {
|
||||
dev_err(fan->dev, "duplicate pwm entry: %s\n",
|
||||
if (pwm_num == MLXREG_FAN_MAX_TACHO) {
|
||||
dev_err(fan->dev, "too many pwm entries: %s\n",
|
||||
data->label);
|
||||
return -EINVAL;
|
||||
}
|
||||
fan->pwm.reg = data->reg;
|
||||
fan->pwm.connected = true;
|
||||
|
||||
/* Validate if more then one PWM is connected. */
|
||||
if (pwm_num) {
|
||||
err = mlxreg_pwm_connect_verify(fan, data);
|
||||
if (err < 0)
|
||||
return err;
|
||||
else if (!err)
|
||||
continue;
|
||||
}
|
||||
|
||||
fan->pwm[pwm_num].reg = data->reg;
|
||||
fan->pwm[pwm_num].connected = true;
|
||||
pwm_num++;
|
||||
} else if (strnstr(data->label, "conf", sizeof(data->label))) {
|
||||
if (configured) {
|
||||
dev_err(fan->dev, "duplicate conf entry: %s\n",
|
||||
|
@ -508,11 +559,32 @@ static int mlxreg_fan_config(struct mlxreg_fan *fan,
|
|||
fan->tachos_per_drwr = tacho_avail / drwr_avail;
|
||||
}
|
||||
|
||||
/* Init cooling levels per PWM state. */
|
||||
for (i = 0; i < MLXREG_FAN_SPEED_MIN_LEVEL; i++)
|
||||
fan->cooling_levels[i] = MLXREG_FAN_SPEED_MIN_LEVEL;
|
||||
for (i = MLXREG_FAN_SPEED_MIN_LEVEL; i <= MLXREG_FAN_MAX_STATE; i++)
|
||||
fan->cooling_levels[i] = i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlxreg_fan_cooling_config(struct device *dev, struct mlxreg_fan *fan)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < MLXREG_FAN_MAX_PWM; i++) {
|
||||
struct mlxreg_fan_pwm *pwm = &fan->pwm[i];
|
||||
|
||||
if (!pwm->connected)
|
||||
continue;
|
||||
pwm->fan = fan;
|
||||
pwm->cdev = devm_thermal_of_cooling_device_register(dev, NULL, mlxreg_fan_name[i],
|
||||
pwm, &mlxreg_fan_cooling_ops);
|
||||
if (IS_ERR(pwm->cdev)) {
|
||||
dev_err(dev, "Failed to register cooling device\n");
|
||||
return PTR_ERR(pwm->cdev);
|
||||
}
|
||||
|
||||
/* Init cooling levels per PWM state. */
|
||||
for (j = 0; j < MLXREG_FAN_SPEED_MIN_LEVEL; j++)
|
||||
pwm->cooling_levels[j] = MLXREG_FAN_SPEED_MIN_LEVEL;
|
||||
for (j = MLXREG_FAN_SPEED_MIN_LEVEL; j <= MLXREG_FAN_MAX_STATE; j++)
|
||||
pwm->cooling_levels[j] = j;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -551,16 +623,10 @@ static int mlxreg_fan_probe(struct platform_device *pdev)
|
|||
return PTR_ERR(hwm);
|
||||
}
|
||||
|
||||
if (IS_REACHABLE(CONFIG_THERMAL)) {
|
||||
fan->cdev = devm_thermal_of_cooling_device_register(dev,
|
||||
NULL, "mlxreg_fan", fan, &mlxreg_fan_cooling_ops);
|
||||
if (IS_ERR(fan->cdev)) {
|
||||
dev_err(dev, "Failed to register cooling device\n");
|
||||
return PTR_ERR(fan->cdev);
|
||||
}
|
||||
}
|
||||
if (IS_REACHABLE(CONFIG_THERMAL))
|
||||
err = mlxreg_fan_cooling_config(dev, fan);
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct platform_driver mlxreg_fan_driver = {
|
||||
|
|
|
@ -174,6 +174,7 @@ superio_exit(int ioreg)
|
|||
#define NCT6683_CUSTOMER_ID_MITAC 0xa0e
|
||||
#define NCT6683_CUSTOMER_ID_MSI 0x201
|
||||
#define NCT6683_CUSTOMER_ID_ASROCK 0xe2c
|
||||
#define NCT6683_CUSTOMER_ID_ASROCK2 0xe1b
|
||||
|
||||
#define NCT6683_REG_BUILD_YEAR 0x604
|
||||
#define NCT6683_REG_BUILD_MONTH 0x605
|
||||
|
@ -1221,6 +1222,8 @@ static int nct6683_probe(struct platform_device *pdev)
|
|||
break;
|
||||
case NCT6683_CUSTOMER_ID_ASROCK:
|
||||
break;
|
||||
case NCT6683_CUSTOMER_ID_ASROCK2:
|
||||
break;
|
||||
default:
|
||||
if (!force)
|
||||
return -ENODEV;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -51,6 +51,23 @@ static const u8 REG_VOLTAGE_LIMIT_MSB_SHIFT[2][5] = {
|
|||
#define REG_CHIP_ID 0xfe
|
||||
#define REG_VERSION_ID 0xff
|
||||
|
||||
/*
|
||||
* Resistance temperature detector (RTD) modes according to 7.2.32 Mode
|
||||
* Selection Register
|
||||
*/
|
||||
#define RTD_MODE_CURRENT 0x1
|
||||
#define RTD_MODE_THERMISTOR 0x2
|
||||
#define RTD_MODE_VOLTAGE 0x3
|
||||
|
||||
#define MODE_RTD_MASK 0x3
|
||||
#define MODE_LTD_EN 0x40
|
||||
|
||||
/*
|
||||
* Bit offset for sensors modes in REG_MODE.
|
||||
* Valid for index 0..2, indicating RTD1..3.
|
||||
*/
|
||||
#define MODE_BIT_OFFSET_RTD(index) ((index) * 2)
|
||||
|
||||
/*
|
||||
* Data structures and manipulation thereof
|
||||
*/
|
||||
|
@ -1038,7 +1055,114 @@ static const struct regmap_config nct7802_regmap_config = {
|
|||
.volatile_reg = nct7802_regmap_is_volatile,
|
||||
};
|
||||
|
||||
static int nct7802_init_chip(struct nct7802_data *data)
|
||||
static int nct7802_get_channel_config(struct device *dev,
|
||||
struct device_node *node, u8 *mode_mask,
|
||||
u8 *mode_val)
|
||||
{
|
||||
u32 reg;
|
||||
const char *type_str, *md_str;
|
||||
u8 md;
|
||||
|
||||
if (!node->name || of_node_cmp(node->name, "channel"))
|
||||
return 0;
|
||||
|
||||
if (of_property_read_u32(node, "reg", ®)) {
|
||||
dev_err(dev, "Could not read reg value for '%s'\n",
|
||||
node->full_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (reg > 3) {
|
||||
dev_err(dev, "Invalid reg (%u) in '%s'\n", reg,
|
||||
node->full_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (reg == 0) {
|
||||
if (!of_device_is_available(node))
|
||||
*mode_val &= ~MODE_LTD_EN;
|
||||
else
|
||||
*mode_val |= MODE_LTD_EN;
|
||||
*mode_mask |= MODE_LTD_EN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* At this point we have reg >= 1 && reg <= 3 */
|
||||
|
||||
if (!of_device_is_available(node)) {
|
||||
*mode_val &= ~(MODE_RTD_MASK << MODE_BIT_OFFSET_RTD(reg - 1));
|
||||
*mode_mask |= MODE_RTD_MASK << MODE_BIT_OFFSET_RTD(reg - 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (of_property_read_string(node, "sensor-type", &type_str)) {
|
||||
dev_err(dev, "No type for '%s'\n", node->full_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!strcmp(type_str, "voltage")) {
|
||||
*mode_val |= (RTD_MODE_VOLTAGE & MODE_RTD_MASK)
|
||||
<< MODE_BIT_OFFSET_RTD(reg - 1);
|
||||
*mode_mask |= MODE_RTD_MASK << MODE_BIT_OFFSET_RTD(reg - 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(type_str, "temperature")) {
|
||||
dev_err(dev, "Invalid type '%s' for '%s'\n", type_str,
|
||||
node->full_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (reg == 3) {
|
||||
/* RTD3 only supports thermistor mode */
|
||||
md = RTD_MODE_THERMISTOR;
|
||||
} else {
|
||||
if (of_property_read_string(node, "temperature-mode",
|
||||
&md_str)) {
|
||||
dev_err(dev, "No mode for '%s'\n", node->full_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!strcmp(md_str, "thermal-diode"))
|
||||
md = RTD_MODE_CURRENT;
|
||||
else if (!strcmp(md_str, "thermistor"))
|
||||
md = RTD_MODE_THERMISTOR;
|
||||
else {
|
||||
dev_err(dev, "Invalid mode '%s' for '%s'\n", md_str,
|
||||
node->full_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
*mode_val |= (md & MODE_RTD_MASK) << MODE_BIT_OFFSET_RTD(reg - 1);
|
||||
*mode_mask |= MODE_RTD_MASK << MODE_BIT_OFFSET_RTD(reg - 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nct7802_configure_channels(struct device *dev,
|
||||
struct nct7802_data *data)
|
||||
{
|
||||
/* Enable local temperature sensor by default */
|
||||
u8 mode_mask = MODE_LTD_EN, mode_val = MODE_LTD_EN;
|
||||
struct device_node *node;
|
||||
int err;
|
||||
|
||||
if (dev->of_node) {
|
||||
for_each_child_of_node(dev->of_node, node) {
|
||||
err = nct7802_get_channel_config(dev, node, &mode_mask,
|
||||
&mode_val);
|
||||
if (err) {
|
||||
of_node_put(node);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return regmap_update_bits(data->regmap, REG_MODE, mode_mask, mode_val);
|
||||
}
|
||||
|
||||
static int nct7802_init_chip(struct device *dev, struct nct7802_data *data)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
@ -1047,8 +1171,7 @@ static int nct7802_init_chip(struct nct7802_data *data)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
/* Enable local temperature sensor */
|
||||
err = regmap_update_bits(data->regmap, REG_MODE, 0x40, 0x40);
|
||||
err = nct7802_configure_channels(dev, data);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -1074,7 +1197,7 @@ static int nct7802_probe(struct i2c_client *client)
|
|||
mutex_init(&data->access_lock);
|
||||
mutex_init(&data->in_alarm_lock);
|
||||
|
||||
ret = nct7802_init_chip(data);
|
||||
ret = nct7802_init_chip(dev, data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -178,7 +178,7 @@ struct pc87360_data {
|
|||
struct device *hwmon_dev;
|
||||
struct mutex lock;
|
||||
struct mutex update_lock;
|
||||
char valid; /* !=0 if following fields are valid */
|
||||
bool valid; /* true if following fields are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
|
||||
int address[3];
|
||||
|
@ -1673,7 +1673,7 @@ static struct pc87360_data *pc87360_update_device(struct device *dev)
|
|||
}
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
data->valid = true;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "pmbus.h"
|
||||
|
||||
#define CFFPS_MFG_ID_CMD 0x99
|
||||
#define CFFPS_FRU_CMD 0x9A
|
||||
#define CFFPS_PN_CMD 0x9B
|
||||
#define CFFPS_HEADER_CMD 0x9C
|
||||
|
@ -34,7 +35,7 @@
|
|||
#define CFFPS_INPUT_HISTORY_SIZE 100
|
||||
|
||||
#define CFFPS_CCIN_REVISION GENMASK(7, 0)
|
||||
#define CFFPS_CCIN_REVISION_LEGACY 0xde
|
||||
#define CFFPS_CCIN_REVISION_LEGACY 0xde
|
||||
#define CFFPS_CCIN_VERSION GENMASK(15, 8)
|
||||
#define CFFPS_CCIN_VERSION_1 0x2b
|
||||
#define CFFPS_CCIN_VERSION_2 0x2e
|
||||
|
@ -57,6 +58,7 @@
|
|||
|
||||
enum {
|
||||
CFFPS_DEBUGFS_INPUT_HISTORY = 0,
|
||||
CFFPS_DEBUGFS_MFG_ID,
|
||||
CFFPS_DEBUGFS_FRU,
|
||||
CFFPS_DEBUGFS_PN,
|
||||
CFFPS_DEBUGFS_HEADER,
|
||||
|
@ -158,6 +160,9 @@ static ssize_t ibm_cffps_debugfs_read(struct file *file, char __user *buf,
|
|||
switch (idx) {
|
||||
case CFFPS_DEBUGFS_INPUT_HISTORY:
|
||||
return ibm_cffps_read_input_history(psu, buf, count, ppos);
|
||||
case CFFPS_DEBUGFS_MFG_ID:
|
||||
cmd = CFFPS_MFG_ID_CMD;
|
||||
break;
|
||||
case CFFPS_DEBUGFS_FRU:
|
||||
cmd = CFFPS_FRU_CMD;
|
||||
break;
|
||||
|
@ -503,16 +508,27 @@ static int ibm_cffps_probe(struct i2c_client *client)
|
|||
u16 ccin_revision = 0;
|
||||
u16 ccin_version = CFFPS_CCIN_VERSION_1;
|
||||
int ccin = i2c_smbus_read_word_swapped(client, CFFPS_CCIN_CMD);
|
||||
char mfg_id[I2C_SMBUS_BLOCK_MAX + 2] = { 0 };
|
||||
|
||||
if (ccin > 0) {
|
||||
ccin_revision = FIELD_GET(CFFPS_CCIN_REVISION, ccin);
|
||||
ccin_version = FIELD_GET(CFFPS_CCIN_VERSION, ccin);
|
||||
}
|
||||
|
||||
rc = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, mfg_id);
|
||||
if (rc < 0) {
|
||||
dev_err(&client->dev, "Failed to read Manufacturer ID\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
switch (ccin_version) {
|
||||
default:
|
||||
case CFFPS_CCIN_VERSION_1:
|
||||
vs = cffps1;
|
||||
if ((strncmp(mfg_id, "ACBE", 4) == 0) ||
|
||||
(strncmp(mfg_id, "ARTE", 4) == 0))
|
||||
vs = cffps1;
|
||||
else
|
||||
vs = cffps2;
|
||||
break;
|
||||
case CFFPS_CCIN_VERSION_2:
|
||||
vs = cffps2;
|
||||
|
@ -564,6 +580,9 @@ static int ibm_cffps_probe(struct i2c_client *client)
|
|||
debugfs_create_file("input_history", 0444, ibm_cffps_dir,
|
||||
&psu->debugfs_entries[CFFPS_DEBUGFS_INPUT_HISTORY],
|
||||
&ibm_cffps_fops);
|
||||
debugfs_create_file("mfg_id", 0444, ibm_cffps_dir,
|
||||
&psu->debugfs_entries[CFFPS_DEBUGFS_MFG_ID],
|
||||
&ibm_cffps_fops);
|
||||
debugfs_create_file("fru", 0444, ibm_cffps_dir,
|
||||
&psu->debugfs_entries[CFFPS_DEBUGFS_FRU],
|
||||
&ibm_cffps_fops);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/of_device.h>
|
||||
#include "pmbus.h"
|
||||
|
||||
enum chips { lm25056, lm25066, lm5064, lm5066, lm5066i };
|
||||
|
@ -51,26 +52,31 @@ struct __coeff {
|
|||
#define PSC_CURRENT_IN_L (PSC_NUM_CLASSES)
|
||||
#define PSC_POWER_L (PSC_NUM_CLASSES + 1)
|
||||
|
||||
static struct __coeff lm25066_coeff[6][PSC_NUM_CLASSES + 2] = {
|
||||
static const struct __coeff lm25066_coeff[][PSC_NUM_CLASSES + 2] = {
|
||||
[lm25056] = {
|
||||
[PSC_VOLTAGE_IN] = {
|
||||
.m = 16296,
|
||||
.b = 1343,
|
||||
.R = -2,
|
||||
},
|
||||
[PSC_CURRENT_IN] = {
|
||||
.m = 13797,
|
||||
.b = -1833,
|
||||
.R = -2,
|
||||
},
|
||||
[PSC_CURRENT_IN_L] = {
|
||||
.m = 6726,
|
||||
.b = -537,
|
||||
.R = -2,
|
||||
},
|
||||
[PSC_POWER] = {
|
||||
.m = 5501,
|
||||
.b = -2908,
|
||||
.R = -3,
|
||||
},
|
||||
[PSC_POWER_L] = {
|
||||
.m = 26882,
|
||||
.b = -5646,
|
||||
.R = -4,
|
||||
},
|
||||
[PSC_TEMPERATURE] = {
|
||||
|
@ -82,26 +88,32 @@ static struct __coeff lm25066_coeff[6][PSC_NUM_CLASSES + 2] = {
|
|||
[lm25066] = {
|
||||
[PSC_VOLTAGE_IN] = {
|
||||
.m = 22070,
|
||||
.b = -1800,
|
||||
.R = -2,
|
||||
},
|
||||
[PSC_VOLTAGE_OUT] = {
|
||||
.m = 22070,
|
||||
.b = -1800,
|
||||
.R = -2,
|
||||
},
|
||||
[PSC_CURRENT_IN] = {
|
||||
.m = 13661,
|
||||
.b = -5200,
|
||||
.R = -2,
|
||||
},
|
||||
[PSC_CURRENT_IN_L] = {
|
||||
.m = 6852,
|
||||
.m = 6854,
|
||||
.b = -3100,
|
||||
.R = -2,
|
||||
},
|
||||
[PSC_POWER] = {
|
||||
.m = 736,
|
||||
.b = -3300,
|
||||
.R = -2,
|
||||
},
|
||||
[PSC_POWER_L] = {
|
||||
.m = 369,
|
||||
.b = -1900,
|
||||
.R = -2,
|
||||
},
|
||||
[PSC_TEMPERATURE] = {
|
||||
|
@ -111,26 +123,32 @@ static struct __coeff lm25066_coeff[6][PSC_NUM_CLASSES + 2] = {
|
|||
[lm5064] = {
|
||||
[PSC_VOLTAGE_IN] = {
|
||||
.m = 4611,
|
||||
.b = -642,
|
||||
.R = -2,
|
||||
},
|
||||
[PSC_VOLTAGE_OUT] = {
|
||||
.m = 4621,
|
||||
.b = 423,
|
||||
.R = -2,
|
||||
},
|
||||
[PSC_CURRENT_IN] = {
|
||||
.m = 10742,
|
||||
.b = 1552,
|
||||
.R = -2,
|
||||
},
|
||||
[PSC_CURRENT_IN_L] = {
|
||||
.m = 5456,
|
||||
.b = 2118,
|
||||
.R = -2,
|
||||
},
|
||||
[PSC_POWER] = {
|
||||
.m = 1204,
|
||||
.b = 8524,
|
||||
.R = -3,
|
||||
},
|
||||
[PSC_POWER_L] = {
|
||||
.m = 612,
|
||||
.b = 11202,
|
||||
.R = -3,
|
||||
},
|
||||
[PSC_TEMPERATURE] = {
|
||||
|
@ -140,26 +158,32 @@ static struct __coeff lm25066_coeff[6][PSC_NUM_CLASSES + 2] = {
|
|||
[lm5066] = {
|
||||
[PSC_VOLTAGE_IN] = {
|
||||
.m = 4587,
|
||||
.b = -1200,
|
||||
.R = -2,
|
||||
},
|
||||
[PSC_VOLTAGE_OUT] = {
|
||||
.m = 4587,
|
||||
.b = -2400,
|
||||
.R = -2,
|
||||
},
|
||||
[PSC_CURRENT_IN] = {
|
||||
.m = 10753,
|
||||
.b = -1200,
|
||||
.R = -2,
|
||||
},
|
||||
[PSC_CURRENT_IN_L] = {
|
||||
.m = 5405,
|
||||
.b = -600,
|
||||
.R = -2,
|
||||
},
|
||||
[PSC_POWER] = {
|
||||
.m = 1204,
|
||||
.b = -6000,
|
||||
.R = -3,
|
||||
},
|
||||
[PSC_POWER_L] = {
|
||||
.m = 605,
|
||||
.b = -8000,
|
||||
.R = -3,
|
||||
},
|
||||
[PSC_TEMPERATURE] = {
|
||||
|
@ -211,8 +235,6 @@ struct lm25066_data {
|
|||
|
||||
#define to_lm25066_data(x) container_of(x, struct lm25066_data, info)
|
||||
|
||||
static const struct i2c_device_id lm25066_id[];
|
||||
|
||||
static int lm25066_read_word_data(struct i2c_client *client, int page,
|
||||
int phase, int reg)
|
||||
{
|
||||
|
@ -413,12 +435,35 @@ static int lm25066_write_word_data(struct i2c_client *client, int page, int reg,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id lm25066_id[] = {
|
||||
{"lm25056", lm25056},
|
||||
{"lm25066", lm25066},
|
||||
{"lm5064", lm5064},
|
||||
{"lm5066", lm5066},
|
||||
{"lm5066i", lm5066i},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, lm25066_id);
|
||||
|
||||
static const struct of_device_id __maybe_unused lm25066_of_match[] = {
|
||||
{ .compatible = "ti,lm25056", .data = (void *)lm25056, },
|
||||
{ .compatible = "ti,lm25066", .data = (void *)lm25066, },
|
||||
{ .compatible = "ti,lm5064", .data = (void *)lm5064, },
|
||||
{ .compatible = "ti,lm5066", .data = (void *)lm5066, },
|
||||
{ .compatible = "ti,lm5066i", .data = (void *)lm5066i, },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lm25066_of_match);
|
||||
|
||||
static int lm25066_probe(struct i2c_client *client)
|
||||
{
|
||||
int config;
|
||||
u32 shunt;
|
||||
struct lm25066_data *data;
|
||||
struct pmbus_driver_info *info;
|
||||
struct __coeff *coeff;
|
||||
const struct __coeff *coeff;
|
||||
const struct of_device_id *of_id;
|
||||
const struct i2c_device_id *i2c_id;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_SMBUS_READ_BYTE_DATA))
|
||||
|
@ -433,7 +478,14 @@ static int lm25066_probe(struct i2c_client *client)
|
|||
if (config < 0)
|
||||
return config;
|
||||
|
||||
data->id = i2c_match_id(lm25066_id, client)->driver_data;
|
||||
i2c_id = i2c_match_id(lm25066_id, client);
|
||||
|
||||
of_id = of_match_device(lm25066_of_match, &client->dev);
|
||||
if (of_id && (unsigned long)of_id->data != i2c_id->driver_data)
|
||||
dev_notice(&client->dev, "Device mismatch: %s in device tree, %s detected\n",
|
||||
of_id->name, i2c_id->name);
|
||||
|
||||
data->id = i2c_id->driver_data;
|
||||
info = &data->info;
|
||||
|
||||
info->pages = 1;
|
||||
|
@ -483,25 +535,25 @@ static int lm25066_probe(struct i2c_client *client)
|
|||
info->b[PSC_POWER] = coeff[PSC_POWER].b;
|
||||
}
|
||||
|
||||
/*
|
||||
* Values in the TI datasheets are normalized for a 1mOhm sense
|
||||
* resistor; assume that unless DT specifies a value explicitly.
|
||||
*/
|
||||
if (of_property_read_u32(client->dev.of_node, "shunt-resistor-micro-ohms", &shunt))
|
||||
shunt = 1000;
|
||||
|
||||
info->m[PSC_CURRENT_IN] = info->m[PSC_CURRENT_IN] * shunt / 1000;
|
||||
info->m[PSC_POWER] = info->m[PSC_POWER] * shunt / 1000;
|
||||
|
||||
return pmbus_do_probe(client, info);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id lm25066_id[] = {
|
||||
{"lm25056", lm25056},
|
||||
{"lm25066", lm25066},
|
||||
{"lm5064", lm5064},
|
||||
{"lm5066", lm5066},
|
||||
{"lm5066i", lm5066i},
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, lm25066_id);
|
||||
|
||||
/* This is the driver that will be inserted */
|
||||
static struct i2c_driver lm25066_driver = {
|
||||
.driver = {
|
||||
.name = "lm25066",
|
||||
},
|
||||
.of_match_table = of_match_ptr(lm25066_of_match),
|
||||
},
|
||||
.probe_new = lm25066_probe,
|
||||
.id_table = lm25066_id,
|
||||
};
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue