提交 64ae88ff 编写于 作者: L Linus Torvalds

Merge tag 'hwmon-for-v5.20' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging

Pull hwmon updates from Guenter Roeck:

 - Substantial rewrite of lm90 driver to support several additional
   chips and improve support for existing chips.

 - Add support of ROG ZENITH II EXTREME, Maximus XI Hero, and
   Strix Z690-a D4 to asus-ec-sensors driver

 - Add support of F71858AD to f71882fg driver

 - Add support of Aquacomputer Quadro to aquacomputer_d5next driver

 - Improved assembler code and add support for Dell G5 5590 as well as
   XPS 13 7390 in dell-smm driver

 - Add support for ASUS TUF GAMING B550-PLUS WIFI II to nct775 driver

 - Add support for IEEE 754 half precision to PMBus core. Also support
   for Analog Devices LT7182S, improve regulator support, and report
   various MFR register values in debugfs.

 - Various other minor improvements and fixes

* tag 'hwmon-for-v5.20' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (85 commits)
  hwmon: (aquacomputer_d5next) Add support for Aquacomputer Quadro fan controller
  hwmon: (dell-smm) Improve documentation
  hwmon: (nct6775) add ASUS TUF GAMING B550-PLUS WIFI II
  hwmon: (occ) Replace open-coded variant of %*phN specifier
  hwmon: (sht15) Fix wrong assumptions in device remove callback
  hwmon: (aquacomputer_d5next) Add support for reading the +12V voltage sensor on D5 Next
  hwmon: (tps23861) fix byte order in current and voltage registers
  hwmon: (aspeed-pwm-tacho) increase fan tach period (again)
  hwmon: (aquacomputer_d5next) Add D5 Next fan control support
  hwmon: (mcp3021) improve driver support for newer hwmon interface
  hwmon: (asus-ec-sensors) add definitions for ROG ZENITH II EXTREME
  hwmon: (aquacomputer_d5next) Move device-specific data into struct aqc_data
  hwmon: (asus-ec-sensors) add missing sensors for X570-I GAMING
  hwmon: (drivetemp) Add module alias
  hwmon: (asus_wmi_sensors) Save a few bytes of memory
  hwmon: (lm90) Use worker for alarm notifications
  hwmon: (asus-ec-sensors) add support for Maximus XI Hero
  hwmon: (dell-smm) Improve assembly code
  hwmon: (pmbus/ltc2978) Set voltage resolution
  hwmon: (pmbus) Add list_voltage to pmbus ops
  ...
...@@ -938,3 +938,12 @@ Description: ...@@ -938,3 +938,12 @@ Description:
- 1: enable - 1: enable
RW RW
What: /sys/class/hwmon/hwmonX/device/pec
Description:
PEC support on I2C devices
- 0, off, n: disable
- 1, on, y: enable
RW
...@@ -16,6 +16,7 @@ properties: ...@@ -16,6 +16,7 @@ properties:
- adi,adm1032 - adi,adm1032
- adi,adt7461 - adi,adt7461
- adi,adt7461a - adi,adt7461a
- adi,adt7481
- dallas,max6646 - dallas,max6646
- dallas,max6647 - dallas,max6647
- dallas,max6649 - dallas,max6649
...@@ -50,6 +51,12 @@ properties: ...@@ -50,6 +51,12 @@ properties:
"#thermal-sensor-cells": "#thermal-sensor-cells":
const: 1 const: 1
'#address-cells':
const: 1
'#size-cells':
const: 0
vcc-supply: vcc-supply:
description: phandle to the regulator that provides the +VCC supply description: phandle to the regulator that provides the +VCC supply
...@@ -61,6 +68,29 @@ required: ...@@ -61,6 +68,29 @@ required:
- compatible - compatible
- reg - reg
patternProperties:
"^channel@([0-2])$":
type: object
description: Represents channels of the device and their specific configuration.
properties:
reg:
description: The channel number. 0 is local channel, 1-2 are remote channels.
items:
minimum: 0
maximum: 2
label:
description: A descriptive name for this channel, like "ambient" or "psu".
temperature-offset-millicelsius:
description: Temperature offset to be added to or subtracted from remote temperature measurements.
required:
- reg
additionalProperties: false
allOf: allOf:
- if: - if:
not: not:
...@@ -70,12 +100,84 @@ allOf: ...@@ -70,12 +100,84 @@ allOf:
enum: enum:
- adi,adt7461 - adi,adt7461
- adi,adt7461a - adi,adt7461a
- adi,adt7481
- ti,tmp451 - ti,tmp451
- ti,tmp461 - ti,tmp461
then: then:
properties: properties:
ti,extended-range-enable: false ti,extended-range-enable: false
- if:
properties:
compatible:
contains:
enum:
- dallas,max6646
- dallas,max6647
- dallas,max6649
- dallas,max6657
- dallas,max6658
- dallas,max6659
- dallas,max6695
- dallas,max6696
then:
patternProperties:
"^channel@([0-2])$":
properties:
temperature-offset-millicelsius: false
- if:
properties:
compatible:
contains:
enum:
- adi,adt7461
- adi,adt7461a
- adi,adt7481
- onnn,nct1008
then:
patternProperties:
"^channel@([0-2])$":
properties:
temperature-offset-millicelsius:
maximum: 127750
- if:
properties:
compatible:
contains:
enum:
- adi,adm1032
- dallas,max6680
- dallas,max6681
- gmt,g781
- national,lm86
- national,lm89
- national,lm90
- national,lm99
- nxp,sa56004
- winbond,w83l771
then:
patternProperties:
"^channel@([0-2])$":
properties:
temperature-offset-millicelsius:
maximum: 127875
- if:
properties:
compatible:
contains:
enum:
- ti,tmp451
- ti,tmp461
then:
patternProperties:
"^channel@([0-2])$":
properties:
temperature-offset-millicelsius:
maximum: 127937
additionalProperties: false additionalProperties: false
examples: examples:
...@@ -94,3 +196,32 @@ examples: ...@@ -94,3 +196,32 @@ examples:
#thermal-sensor-cells = <1>; #thermal-sensor-cells = <1>;
}; };
}; };
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
sensor@4c {
compatible = "adi,adt7481";
reg = <0x4c>;
#address-cells = <1>;
#size-cells = <0>;
channel@0 {
reg = <0x0>;
label = "local";
};
channel@1 {
reg = <0x1>;
label = "front";
temperature-offset-millicelsius = <4000>;
};
channel@2 {
reg = <0x2>;
label = "back";
temperature-offset-millicelsius = <750>;
};
};
};
...@@ -41,6 +41,8 @@ properties: ...@@ -41,6 +41,8 @@ properties:
- adi,adp5585-02 - adi,adp5585-02
# Analog Devices ADP5589 Keypad Decoder and I/O Expansion # Analog Devices ADP5589 Keypad Decoder and I/O Expansion
- adi,adp5589 - adi,adp5589
# Analog Devices LT7182S Dual Channel 6A, 20V PolyPhase Step-Down Silent Switcher
- adi,lt7182s
# AMS iAQ-Core VOC Sensor # AMS iAQ-Core VOC Sensor
- ams,iaq-core - ams,iaq-core
# i2c serial eeprom (24cxx) # i2c serial eeprom (24cxx)
......
...@@ -9,6 +9,7 @@ Supported devices: ...@@ -9,6 +9,7 @@ Supported devices:
* Aquacomputer Farbwerk RGB controller * Aquacomputer Farbwerk RGB controller
* Aquacomputer Farbwerk 360 RGB controller * Aquacomputer Farbwerk 360 RGB controller
* Aquacomputer Octo fan controller * Aquacomputer Octo fan controller
* Aquacomputer Quadro fan controller
Author: Aleksa Savic Author: Aleksa Savic
...@@ -33,6 +34,9 @@ better suited for userspace tools. ...@@ -33,6 +34,9 @@ better suited for userspace tools.
The Octo exposes four temperature sensors and eight PWM controllable fans, along The Octo exposes four temperature sensors and eight PWM controllable fans, along
with their speed (in RPM), power, voltage and current. with their speed (in RPM), power, voltage and current.
The Quadro exposes four temperature sensors, a flow sensor and four PWM controllable
fans, along with their speed (in RPM), power, voltage and current.
The Farbwerk and Farbwerk 360 expose four temperature sensors. Depending on the device, The Farbwerk and Farbwerk 360 expose four temperature sensors. Depending on the device,
not all sysfs and debugfs entries will be available. not all sysfs and debugfs entries will be available.
...@@ -45,13 +49,14 @@ the kernel and supports hotswapping. ...@@ -45,13 +49,14 @@ the kernel and supports hotswapping.
Sysfs entries Sysfs entries
------------- -------------
================ ============================================= ================ ==============================================
temp[1-4]_input Temperature sensors (in millidegrees Celsius) temp[1-4]_input Temperature sensors (in millidegrees Celsius)
fan[1-2]_input Pump/fan speed (in RPM) fan[1-8]_input Pump/fan speed (in RPM) / Flow speed (in dL/h)
power[1-2]_input Pump/fan power (in micro Watts) power[1-8]_input Pump/fan power (in micro Watts)
in[0-2]_input Pump/fan voltage (in milli Volts) in[0-7]_input Pump/fan voltage (in milli Volts)
curr[1-2]_input Pump/fan current (in milli Amperes) curr[1-8]_input Pump/fan current (in milli Amperes)
================ ============================================= pwm[1-8] Fan PWM (0 - 255)
================ ==============================================
Debugfs entries Debugfs entries
--------------- ---------------
......
...@@ -13,12 +13,16 @@ Supported boards: ...@@ -13,12 +13,16 @@ Supported boards:
* ROG CROSSHAIR VIII FORMULA * ROG CROSSHAIR VIII FORMULA
* ROG CROSSHAIR VIII HERO * ROG CROSSHAIR VIII HERO
* ROG CROSSHAIR VIII IMPACT * ROG CROSSHAIR VIII IMPACT
* ROG MAXIMUS XI HERO
* ROG MAXIMUS XI HERO (WI-FI)
* ROG STRIX B550-E GAMING * ROG STRIX B550-E GAMING
* ROG STRIX B550-I GAMING * ROG STRIX B550-I GAMING
* ROG STRIX X570-E GAMING * ROG STRIX X570-E GAMING
* ROG STRIX X570-E GAMING WIFI II * ROG STRIX X570-E GAMING WIFI II
* ROG STRIX X570-F GAMING * ROG STRIX X570-F GAMING
* ROG STRIX X570-I GAMING * ROG STRIX X570-I GAMING
* ROG STRIX Z690-A GAMING WIFI D4
* ROG ZENITH II EXTREME
Authors: Authors:
- Eugene Shalygin <eugene.shalygin@gmail.com> - Eugene Shalygin <eugene.shalygin@gmail.com>
......
...@@ -46,6 +46,9 @@ temp[1-10]_input RO Temperature reading in milli-degrees ...@@ -46,6 +46,9 @@ temp[1-10]_input RO Temperature reading in milli-degrees
temp[1-10]_label RO Temperature sensor label. temp[1-10]_label RO Temperature sensor label.
=============================== ======= ======================================= =============================== ======= =======================================
Due to the nature of the SMM interface, each pwmX attribute controls
fan number X.
Disabling automatic BIOS fan control Disabling automatic BIOS fan control
------------------------------------ ------------------------------------
......
...@@ -109,6 +109,7 @@ Hardware Monitoring Kernel Drivers ...@@ -109,6 +109,7 @@ Hardware Monitoring Kernel Drivers
lm95234 lm95234
lm95245 lm95245
lochnagar lochnagar
lt7182s
ltc2992 ltc2992
ltc2945 ltc2945
ltc2947 ltc2947
......
...@@ -3,6 +3,14 @@ Kernel driver lm90 ...@@ -3,6 +3,14 @@ Kernel driver lm90
Supported chips: Supported chips:
* National Semiconductor LM84
Prefix: 'lm84'
Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
Datasheet: Publicly available at the National Semiconductor website
* National Semiconductor LM90 * National Semiconductor LM90
Prefix: 'lm90' Prefix: 'lm90'
...@@ -43,6 +51,30 @@ Supported chips: ...@@ -43,6 +51,30 @@ Supported chips:
http://www.national.com/mpf/LM/LM86.html http://www.national.com/mpf/LM/LM86.html
* Analog Devices ADM1020
Prefix: 'adm1020'
Addresses scanned: I2C 0x4c - 0x4e
Datasheet: Publicly available at the Analog Devices website
* Analog Devices ADM1021
Prefix: 'adm1021'
Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
Datasheet: Publicly available at the Analog Devices website
* Analog Devices ADM1021A/ADM1023
Prefix: 'adm1023'
Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
Datasheet: Publicly available at the Analog Devices website
* Analog Devices ADM1032 * Analog Devices ADM1032
Prefix: 'adm1032' Prefix: 'adm1032'
...@@ -73,6 +105,36 @@ Supported chips: ...@@ -73,6 +105,36 @@ Supported chips:
https://www.onsemi.com/PowerSolutions/product.do?id=ADT7461A https://www.onsemi.com/PowerSolutions/product.do?id=ADT7461A
* Analog Devices ADT7481
Prefix: 'adt7481'
Addresses scanned: I2C 0x4b and 0x4c
Datasheet: Publicly available at the ON Semiconductor website
https://www.onsemi.com/PowerSolutions/product.do?id=ADT7481
* Analog Devices ADT7482
Prefix: 'adt7482'
Addresses scanned: I2C 0x4c
Datasheet: Publicly available at the ON Semiconductor website
https://www.onsemi.com/PowerSolutions/product.do?id=ADT7482
* Analog Devices ADT7483A
Prefix: 'adt7483a'
Addresses scanned: I2C 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e
Datasheet: Publicly available at the ON Semiconductor website
https://www.onsemi.com/PowerSolutions/product.do?id=ADT7483A
* ON Semiconductor NCT1008 * ON Semiconductor NCT1008
Prefix: 'nct1008' Prefix: 'nct1008'
...@@ -83,6 +145,72 @@ Supported chips: ...@@ -83,6 +145,72 @@ Supported chips:
https://www.onsemi.com/PowerSolutions/product.do?id=NCT1008 https://www.onsemi.com/PowerSolutions/product.do?id=NCT1008
* ON Semiconductor NCT210
Prefix: 'adm1021'
Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
Datasheet: Publicly available at the ON Semiconductor website
https://www.onsemi.com/PowerSolutions/product.do?id=NCT210
* ON Semiconductor NCT214
Prefix: 'nct214'
Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
Datasheet: Publicly available at the ON Semiconductor website
https://www.onsemi.com/PowerSolutions/product.do?id=NCT214
* ON Semiconductor NCT218
Prefix: 'nct218'
Addresses scanned: I2C 0x4c - 0x4d
Datasheet: Publicly available at the ON Semiconductor website
https://www.onsemi.com/PowerSolutions/product.do?id=NCT218
* ON Semiconductor NCT72
Prefix: 'nct72'
Addresses scanned: I2C 0x4c - 0x4d
Datasheet: Publicly available at the ON Semiconductor website
https://www.onsemi.com/PowerSolutions/product.do?id=NCT72
* Maxim MAX1617
Prefix: 'max1617'
Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
Datasheet: Publicly available at the Maxim website
* Maxim MAX1617A
Prefix: 'max1617a'
Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
Datasheet: Publicly available at the Maxim website
* Maxim MAX6642
Prefix: 'max6642'
Addresses scanned: I2C 0x48-0x4f
Datasheet: Publicly available at the Maxim website
http://datasheets.maxim-ic.com/en/ds/MAX6642.pdf
* Maxim MAX6646 * Maxim MAX6646
Prefix: 'max6646' Prefix: 'max6646'
...@@ -105,7 +233,7 @@ Supported chips: ...@@ -105,7 +233,7 @@ Supported chips:
* Maxim MAX6648 * Maxim MAX6648
Prefix: 'max6646' Prefix: 'max6648'
Addresses scanned: I2C 0x4c Addresses scanned: I2C 0x4c
...@@ -191,7 +319,7 @@ Supported chips: ...@@ -191,7 +319,7 @@ Supported chips:
* Maxim MAX6692 * Maxim MAX6692
Prefix: 'max6646' Prefix: 'max6648'
Addresses scanned: I2C 0x4c Addresses scanned: I2C 0x4c
...@@ -275,6 +403,46 @@ Supported chips: ...@@ -275,6 +403,46 @@ Supported chips:
https://www.ti.com/lit/gpn/tmp461 https://www.ti.com/lit/gpn/tmp461
* Philips NE1617, NE1617A
Prefix: 'max1617' (probably detected as a max1617)
Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
Datasheets: Publicly available at the Philips website
* Philips NE1618
Prefix: 'ne1618'
Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
Datasheets: Publicly available at the Philips website
* Genesys Logic GL523SM
Prefix: 'gl523sm'
Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
Datasheet:
* TI THMC10
Prefix: 'thmc10'
Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
Datasheet: Publicly available at the TI website
* Onsemi MC1066
Prefix: 'mc1066'
Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
Datasheet: Publicly available at the Onsemi website
Author: Jean Delvare <jdelvare@suse.de> Author: Jean Delvare <jdelvare@suse.de>
...@@ -285,6 +453,12 @@ The LM90 is a digital temperature sensor. It senses its own temperature as ...@@ -285,6 +453,12 @@ The LM90 is a digital temperature sensor. It senses its own temperature as
well as the temperature of up to one external diode. It is compatible well as the temperature of up to one external diode. It is compatible
with many other devices, many of which are supported by this driver. with many other devices, many of which are supported by this driver.
The family of chips supported by this driver is derived from MAX1617.
This chip as well as various compatible chips support a local and a remote
temperature sensor with 8 bit accuracy. Later chips provide improved accuracy
and other additional features such as hysteresis and temperature offset
registers.
Note that there is no easy way to differentiate between the MAX6657, Note that there is no easy way to differentiate between the MAX6657,
MAX6658 and MAX6659 variants. The extra features of the MAX6659 are only MAX6658 and MAX6659 variants. The extra features of the MAX6659 are only
supported by this driver if the chip is located at address 0x4d or 0x4e, supported by this driver if the chip is located at address 0x4d or 0x4e,
...@@ -292,15 +466,31 @@ or if the chip type is explicitly selected as max6659. ...@@ -292,15 +466,31 @@ or if the chip type is explicitly selected as max6659.
The MAX6680 and MAX6681 only differ in their pinout, therefore they obviously The MAX6680 and MAX6681 only differ in their pinout, therefore they obviously
can't (and don't need to) be distinguished. can't (and don't need to) be distinguished.
The specificity of this family of chipsets over the ADM1021/LM84
family is that it features critical limits with hysteresis, and an
increased resolution of the remote temperature measurement.
The different chipsets of the family are not strictly identical, although The different chipsets of the family are not strictly identical, although
very similar. For reference, here comes a non-exhaustive list of specific very similar. For reference, here comes a non-exhaustive list of specific
features: features:
LM84:
* 8 bit sensor resolution
ADM1020, ADM1021, GL523SM, MAX1617, NE1617, NE1617A, THMC10:
* 8 bit sensor resolution
* Low temperature limits
NCT210, NE1618:
* 11 bit sensor resolution for remote temperature sensor
* Low temperature limits
ADM1021A, ADM1023:
* Temperature offset register for remote temperature sensor
* 11 bit resolution for remote temperature sensor
* Low temperature limits
LM90: LM90:
* 11 bit resolution for remote temperature sensor
* Temperature offset register for remote temperature sensor
* Low and critical temperature limits
* Configurable conversion rate
* Filter and alert configuration register at 0xBF. * Filter and alert configuration register at 0xBF.
* ALERT is triggered by temperatures over critical limits. * ALERT is triggered by temperatures over critical limits.
...@@ -322,8 +512,31 @@ ADM1032: ...@@ -322,8 +512,31 @@ ADM1032:
ADT7461, ADT7461A, NCT1008: ADT7461, ADT7461A, NCT1008:
* Extended temperature range (breaks compatibility) * Extended temperature range (breaks compatibility)
* Lower resolution for remote temperature * Lower resolution for remote temperature
* SMBus PEC support for Write Byte and Receive Byte transactions.
* 10 bit temperature resolution
ADT7481, ADT7482, ADT7483:
* Temperature offset register
* SMBus PEC support
* 10 bit temperature resolution for external sensors
* Two remote sensors
* Selectable address (ADT7483)
MAX6642:
* No critical limit register
* Conversion rate not configurable
* Better local resolution (10 bit)
* 10 bit external sensor resolution
MAX6646, MAX6647, MAX6649:
* Better local resolution
* Extended range unsigned external temperature
MAX6648, MAX6692:
* Better local resolution
* Unsigned temperature
MAX6654: MAX6654, MAX6690:
* Better local resolution * Better local resolution
* Selectable address * Selectable address
* Remote sensor type selection * Remote sensor type selection
...@@ -423,6 +636,6 @@ two transactions will typically mean twice as much delay waiting for ...@@ -423,6 +636,6 @@ two transactions will typically mean twice as much delay waiting for
transaction completion, effectively doubling the register cache refresh time. transaction completion, effectively doubling the register cache refresh time.
I guess reliability comes at a price, but it's quite expensive this time. I guess reliability comes at a price, but it's quite expensive this time.
So, as not everyone might enjoy the slowdown, PEC can be disabled through So, as not everyone might enjoy the slowdown, PEC is disabled by default and
sysfs. Just write 0 to the "pec" file and PEC will be disabled. Write 1 can be enabled through sysfs. Just write 1 to the "pec" file and PEC will be
to that file to enable PEC again. enabled. Write 0 to that file to disable PEC again.
.. SPDX-License-Identifier: GPL-2.0
Kernel driver lt7182s
=====================
Supported chips:
* ADI LT7182S
Prefix: 'lt7182s'
Addresses scanned: -
Datasheet: https://www.analog.com/en/products/lt7182s.html
Author: Guenter Roeck <linux@roeck-us.net>
Description
-----------
LT7182S is a Dual Channel 6A, 20V PolyPhase Step-Down Silent Switcher with
Digital Power System Management support.
Usage Notes
-----------
This driver does not probe for PMBus devices. You will have to instantiate
devices explicitly.
Example: the following commands will load the driver for a LT7182S
at address 0x4f on I2C bus #4::
# modprobe lt7182s
# echo lt7182s 0x4f > /sys/bus/i2c/devices/i2c-4/new_device
It can also be instantiated by declaring an entry in device tree.
Sysfs attributes
----------------
======================= ====================================
curr[1-2]_label "iin[12]"
curr[1-2]_input Measured input current
curr[1-2]_max Maximum input current
curr[1-2]_max_alarm Current high alarm
curr[3-4]_label "iout[1-2]"
curr[3-4]_input Measured output current
curr[3-4]_highest Highest measured output current
curr[3-4]_max Maximum output current
curr[3-4]_max_alarm Output current high alarm
in[1-2]_label "vin[12]"
in[1-2]_input Measured input voltage
in[1-2]_highest Highest measured input voltage
in[1-2]_crit Critical maximum input voltage
in[1-2]_crit_alarm Input voltage critical high alarm
in[1-2]_min Minimum input voltage
in[1-2]_min_alarm Input voltage low alarm
in[1-2]_rated_min Rated minimum input voltage
in[1-2]_rated_max Rated maximum input voltage
in1_reset_history Write to reset history for all attributes
in[3-5]_label "vmon[1-3]"
in[3-5]_input Measured voltage on ITH1/ITH2/EXTVCC pins
Only available if enabled with MFR_ADC_CONTROL_LT7182S
command.
in[3-4|6-7]_label "vout[1-2]"
in[3-4|6-7]_input Measured output voltage
in[3-4|6-7]_highest Highest measured output voltage
in[3-4|6-7]_lcrit Critical minimum output voltage
in[3-4|6-7]_lcrit_alarm Output voltage critical low alarm
in[3-4|6-7]_min Minimum output voltage
in[3-4|6-7]_max_alarm Output voltage low alarm
in[3-4|6-7]_max Maximum output voltage
in[3-4|6-7]_max_alarm Output voltage high alarm
in[3-4|6-7]_crit Critical maximum output voltage
in[3-4|6-7]_crit_alarm Output voltage critical high alarm
power[1-2]_label "pout[1-2]"
power[1-2]_input Measured output power
temp1_input Measured temperature
temp1_crit Critical high temperature
temp1_crit_alarm Chip temperature critical high alarm
temp1_max Maximum temperature
temp1_max_alarm Chip temperature high alarm
======================= ====================================
...@@ -121,6 +121,15 @@ Specifically, it provides the following information. ...@@ -121,6 +121,15 @@ Specifically, it provides the following information.
non-standard PMBus commands to standard commands, or to augment standard non-standard PMBus commands to standard commands, or to augment standard
command return values with device specific information. command return values with device specific information.
PEC Support
===========
Many PMBus devices support SMBus PEC (Packet Error Checking). If supported
by both the I2C adapter and by the PMBus chip, it is by default enabled.
If PEC is supported, the PMBus core driver adds an attribute named 'pec' to
the I2C device. This attribute can be used to control PEC support in the
communication with the PMBus chip.
API functions API functions
============= =============
......
...@@ -100,6 +100,7 @@ config SENSORS_AD7418 ...@@ -100,6 +100,7 @@ config SENSORS_AD7418
config SENSORS_ADM1021 config SENSORS_ADM1021
tristate "Analog Devices ADM1021 and compatibles" tristate "Analog Devices ADM1021 and compatibles"
depends on I2C depends on I2C
depends on SENSORS_LM90=n
help help
If you say yes here you get support for Analog Devices ADM1021 If you say yes here you get support for Analog Devices ADM1021
and ADM1023 sensor chips and clones: Maxim MAX1617 and MAX1617A, and ADM1023 sensor chips and clones: Maxim MAX1617 and MAX1617A,
...@@ -256,13 +257,13 @@ config SENSORS_AHT10 ...@@ -256,13 +257,13 @@ config SENSORS_AHT10
will be called aht10. will be called aht10.
config SENSORS_AQUACOMPUTER_D5NEXT config SENSORS_AQUACOMPUTER_D5NEXT
tristate "Aquacomputer D5 Next, Octo, Farbwerk, and Farbwerk 360" tristate "Aquacomputer D5 Next, Octo, Quadro, Farbwerk, and Farbwerk 360"
depends on USB_HID depends on USB_HID
select CRC16 select CRC16
help help
If you say yes here you get support for sensors and fans of If you say yes here you get support for sensors and fans of
the Aquacomputer D5 Next watercooling pump, Octo fan the Aquacomputer D5 Next watercooling pump, Octo and Quadro fan
controller, Farbwerk and Farbwerk 360 RGB controllers, where controllers, Farbwerk and Farbwerk 360 RGB controllers, where
available. available.
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
...@@ -381,7 +382,7 @@ config SENSORS_ARM_SCPI ...@@ -381,7 +382,7 @@ config SENSORS_ARM_SCPI
config SENSORS_ASB100 config SENSORS_ASB100
tristate "Asus ASB100 Bach" tristate "Asus ASB100 Bach"
depends on X86 && I2C depends on (X86 || COMPILE_TEST) && I2C
select HWMON_VID select HWMON_VID
help help
If you say yes here you get support for the ASB100 Bach sensor If you say yes here you get support for the ASB100 Bach sensor
...@@ -626,7 +627,7 @@ config SENSORS_MC13783_ADC ...@@ -626,7 +627,7 @@ config SENSORS_MC13783_ADC
config SENSORS_FSCHMD config SENSORS_FSCHMD
tristate "Fujitsu Siemens Computers sensor chips" tristate "Fujitsu Siemens Computers sensor chips"
depends on X86 && I2C depends on (X86 || COMPILE_TEST) && I2C
help help
If you say yes here you get support for the following Fujitsu If you say yes here you get support for the following Fujitsu
Siemens Computers (FSC) sensor chips: Poseidon, Scylla, Hermes, Siemens Computers (FSC) sensor chips: Poseidon, Scylla, Hermes,
...@@ -1102,6 +1103,7 @@ config SENSORS_MAX6639 ...@@ -1102,6 +1103,7 @@ config SENSORS_MAX6639
config SENSORS_MAX6642 config SENSORS_MAX6642
tristate "Maxim MAX6642 sensor chip" tristate "Maxim MAX6642 sensor chip"
depends on I2C depends on I2C
depends on SENSORS_LM90=n
help help
If you say yes here you get support for MAX6642 sensor chip. If you say yes here you get support for MAX6642 sensor chip.
MAX6642 is a SMBus-Compatible Remote/Local Temperature Sensor MAX6642 is a SMBus-Compatible Remote/Local Temperature Sensor
...@@ -1357,12 +1359,15 @@ config SENSORS_LM90 ...@@ -1357,12 +1359,15 @@ config SENSORS_LM90
tristate "National Semiconductor LM90 and compatibles" tristate "National Semiconductor LM90 and compatibles"
depends on I2C depends on I2C
help help
If you say yes here you get support for National Semiconductor LM90, If you say yes here you get support for National Semiconductor LM84,
LM86, LM89 and LM99, Analog Devices ADM1032, ADT7461, and ADT7461A, LM90, LM86, LM89 and LM99, Analog Devices ADM1020, ADM2021, ADM1021A,
Maxim MAX6646, MAX6647, MAX6648, MAX6649, MAX6654, MAX6657, MAX6658, ADM1023, ADM1032, ADT7461, ADT7461A, ADT7481, ADT7482, and ADT7483A,
MAX6659, MAX6680, MAX6681, MAX6692, MAX6695, MAX6696, Maxim MAX1617, MAX6642, MAX6646, MAX6647, MAX6648, MAX6649, MAX6654,
ON Semiconductor NCT1008, Winbond/Nuvoton W83L771W/G/AWG/ASG, MAX6657, MAX6658, MAX6659, MAX6680, MAX6681, MAX6692, MAX6695,
Philips SA56004, GMT G781, Texas Instruments TMP451 and TMP461 MAX6696,
ON Semiconductor NCT1008, NCT210, NCT72, NCT214, NCT218,
Winbond/Nuvoton W83L771W/G/AWG/ASG,
Philips NE1618, SA56004, GMT G781, Texas Instruments TMP451 and TMP461
sensor chips. sensor chips.
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
......
// SPDX-License-Identifier: GPL-2.0+ // SPDX-License-Identifier: GPL-2.0+
/* /*
* hwmon driver for Aquacomputer devices (D5 Next, Farbwerk, Farbwerk 360, Octo) * hwmon driver for Aquacomputer devices (D5 Next, Farbwerk, Farbwerk 360, Octo,
* Quadro)
* *
* Aquacomputer devices send HID reports (with ID 0x01) every second to report * Aquacomputer devices send HID reports (with ID 0x01) every second to report
* sensor values. * sensor values.
...@@ -21,17 +22,19 @@ ...@@ -21,17 +22,19 @@
#define USB_VENDOR_ID_AQUACOMPUTER 0x0c70 #define USB_VENDOR_ID_AQUACOMPUTER 0x0c70
#define USB_PRODUCT_ID_FARBWERK 0xf00a #define USB_PRODUCT_ID_FARBWERK 0xf00a
#define USB_PRODUCT_ID_QUADRO 0xf00d
#define USB_PRODUCT_ID_D5NEXT 0xf00e #define USB_PRODUCT_ID_D5NEXT 0xf00e
#define USB_PRODUCT_ID_FARBWERK360 0xf010 #define USB_PRODUCT_ID_FARBWERK360 0xf010
#define USB_PRODUCT_ID_OCTO 0xf011 #define USB_PRODUCT_ID_OCTO 0xf011
enum kinds { d5next, farbwerk, farbwerk360, octo }; enum kinds { d5next, farbwerk, farbwerk360, octo, quadro };
static const char *const aqc_device_names[] = { static const char *const aqc_device_names[] = {
[d5next] = "d5next", [d5next] = "d5next",
[farbwerk] = "farbwerk", [farbwerk] = "farbwerk",
[farbwerk360] = "farbwerk360", [farbwerk360] = "farbwerk360",
[octo] = "octo" [octo] = "octo",
[quadro] = "quadro"
}; };
#define DRIVER_NAME "aquacomputer_d5next" #define DRIVER_NAME "aquacomputer_d5next"
...@@ -54,60 +57,61 @@ static u8 secondary_ctrl_report[] = { ...@@ -54,60 +57,61 @@ static u8 secondary_ctrl_report[] = {
0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x34, 0xC6 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x34, 0xC6
}; };
/* Register offsets for the D5 Next pump */ /* Register offsets for all Aquacomputer devices */
#define D5NEXT_POWER_CYCLES 24 #define AQC_TEMP_SENSOR_SIZE 0x02
#define AQC_TEMP_SENSOR_DISCONNECTED 0x7FFF
#define D5NEXT_COOLANT_TEMP 87 #define AQC_FAN_PERCENT_OFFSET 0x00
#define AQC_FAN_VOLTAGE_OFFSET 0x02
#define D5NEXT_PUMP_SPEED 116 #define AQC_FAN_CURRENT_OFFSET 0x04
#define D5NEXT_FAN_SPEED 103 #define AQC_FAN_POWER_OFFSET 0x06
#define AQC_FAN_SPEED_OFFSET 0x08
#define D5NEXT_PUMP_POWER 114
#define D5NEXT_FAN_POWER 101
#define D5NEXT_PUMP_VOLTAGE 110
#define D5NEXT_FAN_VOLTAGE 97
#define D5NEXT_5V_VOLTAGE 57
#define D5NEXT_PUMP_CURRENT 112 /* Register offsets for the D5 Next pump */
#define D5NEXT_FAN_CURRENT 99 #define D5NEXT_POWER_CYCLES 0x18
#define D5NEXT_COOLANT_TEMP 0x57
#define D5NEXT_NUM_FANS 2
#define D5NEXT_NUM_SENSORS 1
#define D5NEXT_PUMP_OFFSET 0x6c
#define D5NEXT_FAN_OFFSET 0x5f
#define D5NEXT_5V_VOLTAGE 0x39
#define D5NEXT_12V_VOLTAGE 0x37
#define D5NEXT_CTRL_REPORT_SIZE 0x329
static u8 d5next_sensor_fan_offsets[] = { D5NEXT_PUMP_OFFSET, D5NEXT_FAN_OFFSET };
/* Pump and fan speed registers in D5 Next control report (from 0-100%) */
static u16 d5next_ctrl_fan_offsets[] = { 0x97, 0x42 };
/* Register offsets for the Farbwerk RGB controller */ /* Register offsets for the Farbwerk RGB controller */
#define FARBWERK_NUM_SENSORS 4 #define FARBWERK_NUM_SENSORS 4
#define FARBWERK_SENSOR_START 0x2f #define FARBWERK_SENSOR_START 0x2f
#define FARBWERK_SENSOR_SIZE 0x02
#define FARBWERK_SENSOR_DISCONNECTED 0x7FFF
/* Register offsets for the Farbwerk 360 RGB controller */ /* Register offsets for the Farbwerk 360 RGB controller */
#define FARBWERK360_NUM_SENSORS 4 #define FARBWERK360_NUM_SENSORS 4
#define FARBWERK360_SENSOR_START 0x32 #define FARBWERK360_SENSOR_START 0x32
#define FARBWERK360_SENSOR_SIZE 0x02
#define FARBWERK360_SENSOR_DISCONNECTED 0x7FFF
/* Register offsets for the Octo fan controller */ /* Register offsets for the Octo fan controller */
#define OCTO_POWER_CYCLES 0x18 #define OCTO_POWER_CYCLES 0x18
#define OCTO_NUM_FANS 8 #define OCTO_NUM_FANS 8
#define OCTO_FAN_PERCENT_OFFSET 0x00
#define OCTO_FAN_VOLTAGE_OFFSET 0x02
#define OCTO_FAN_CURRENT_OFFSET 0x04
#define OCTO_FAN_POWER_OFFSET 0x06
#define OCTO_FAN_SPEED_OFFSET 0x08
static u8 octo_sensor_fan_offsets[] = { 0x7D, 0x8A, 0x97, 0xA4, 0xB1, 0xBE, 0xCB, 0xD8 };
#define OCTO_NUM_SENSORS 4 #define OCTO_NUM_SENSORS 4
#define OCTO_SENSOR_START 0x3D #define OCTO_SENSOR_START 0x3D
#define OCTO_SENSOR_SIZE 0x02 #define OCTO_CTRL_REPORT_SIZE 0x65F
#define OCTO_SENSOR_DISCONNECTED 0x7FFF static u8 octo_sensor_fan_offsets[] = { 0x7D, 0x8A, 0x97, 0xA4, 0xB1, 0xBE, 0xCB, 0xD8 };
#define OCTO_CTRL_REPORT_SIZE 0x65F
#define OCTO_CTRL_REPORT_CHECKSUM_OFFSET 0x65D
#define OCTO_CTRL_REPORT_CHECKSUM_START 0x01
#define OCTO_CTRL_REPORT_CHECKSUM_LENGTH 0x65C
/* Fan speed registers in Octo control report (from 0-100%) */ /* Fan speed registers in Octo control report (from 0-100%) */
static u16 octo_ctrl_fan_offsets[] = { 0x5B, 0xB0, 0x105, 0x15A, 0x1AF, 0x204, 0x259, 0x2AE }; static u16 octo_ctrl_fan_offsets[] = { 0x5B, 0xB0, 0x105, 0x15A, 0x1AF, 0x204, 0x259, 0x2AE };
/* Register offsets for the Quadro fan controller */
#define QUADRO_POWER_CYCLES 0x18
#define QUADRO_NUM_FANS 4
#define QUADRO_NUM_SENSORS 4
#define QUADRO_SENSOR_START 0x34
#define QUADRO_CTRL_REPORT_SIZE 0x3c1
#define QUADRO_FLOW_SENSOR_OFFSET 0x6e
static u8 quadro_sensor_fan_offsets[] = { 0x70, 0x7D, 0x8A, 0x97 };
/* Fan speed registers in Quadro control report (from 0-100%) */
static u16 quadro_ctrl_fan_offsets[] = { 0x36, 0x8b, 0xe0, 0x135 };
/* Labels for D5 Next */ /* Labels for D5 Next */
static const char *const label_d5next_temp[] = { static const char *const label_d5next_temp[] = {
"Coolant temp" "Coolant temp"
...@@ -126,7 +130,8 @@ static const char *const label_d5next_power[] = { ...@@ -126,7 +130,8 @@ static const char *const label_d5next_power[] = {
static const char *const label_d5next_voltages[] = { static const char *const label_d5next_voltages[] = {
"Pump voltage", "Pump voltage",
"Fan voltage", "Fan voltage",
"+5V voltage" "+5V voltage",
"+12V voltage"
}; };
static const char *const label_d5next_current[] = { static const char *const label_d5next_current[] = {
...@@ -134,7 +139,7 @@ static const char *const label_d5next_current[] = { ...@@ -134,7 +139,7 @@ static const char *const label_d5next_current[] = {
"Fan current" "Fan current"
}; };
/* Labels for Farbwerk, Farbwerk 360 and Octo temperature sensors */ /* Labels for Farbwerk, Farbwerk 360 and Octo and Quadro temperature sensors */
static const char *const label_temp_sensors[] = { static const char *const label_temp_sensors[] = {
"Sensor 1", "Sensor 1",
"Sensor 2", "Sensor 2",
...@@ -142,7 +147,7 @@ static const char *const label_temp_sensors[] = { ...@@ -142,7 +147,7 @@ static const char *const label_temp_sensors[] = {
"Sensor 4" "Sensor 4"
}; };
/* Labels for Octo */ /* Labels for Octo and Quadro (except speed) */
static const char *const label_fan_speed[] = { static const char *const label_fan_speed[] = {
"Fan 1 speed", "Fan 1 speed",
"Fan 2 speed", "Fan 2 speed",
...@@ -187,6 +192,15 @@ static const char *const label_fan_current[] = { ...@@ -187,6 +192,15 @@ static const char *const label_fan_current[] = {
"Fan 8 current" "Fan 8 current"
}; };
/* Labels for Quadro fan speeds */
static const char *const label_quadro_speeds[] = {
"Fan 1 speed",
"Fan 2 speed",
"Fan 3 speed",
"Fan 4 speed",
"Flow speed [dL/h]"
};
struct aqc_data { struct aqc_data {
struct hid_device *hdev; struct hid_device *hdev;
struct device *hwmon_dev; struct device *hwmon_dev;
...@@ -201,11 +215,19 @@ struct aqc_data { ...@@ -201,11 +215,19 @@ struct aqc_data {
int checksum_length; int checksum_length;
int checksum_offset; int checksum_offset;
int num_fans;
u8 *fan_sensor_offsets;
u16 *fan_ctrl_offsets;
int num_temp_sensors;
int temp_sensor_start_offset;
u16 power_cycle_count_offset;
u8 flow_sensor_offset;
/* General info, same across all devices */ /* General info, same across all devices */
u32 serial_number[2]; u32 serial_number[2];
u16 firmware_version; u16 firmware_version;
/* How many times the device was powered on */ /* How many times the device was powered on, if available */
u32 power_cycles; u32 power_cycles;
/* Sensor values */ /* Sensor values */
...@@ -323,56 +345,47 @@ static umode_t aqc_is_visible(const void *data, enum hwmon_sensor_types type, u3 ...@@ -323,56 +345,47 @@ static umode_t aqc_is_visible(const void *data, enum hwmon_sensor_types type, u3
switch (type) { switch (type) {
case hwmon_temp: case hwmon_temp:
switch (priv->kind) { if (channel < priv->num_temp_sensors)
case d5next:
if (channel == 0)
return 0444;
break;
case farbwerk:
case farbwerk360:
case octo:
return 0444; return 0444;
default:
break;
}
break; break;
case hwmon_pwm: case hwmon_pwm:
switch (priv->kind) { if (priv->fan_ctrl_offsets && channel < priv->num_fans) {
case octo:
switch (attr) { switch (attr) {
case hwmon_pwm_input: case hwmon_pwm_input:
return 0644; return 0644;
default: default:
break; break;
} }
break;
default:
break;
} }
break; break;
case hwmon_fan: case hwmon_fan:
case hwmon_power:
case hwmon_curr:
switch (priv->kind) { switch (priv->kind) {
case d5next: case quadro:
if (channel < 2) /* Special case to support flow sensor */
if (channel < priv->num_fans + 1)
return 0444; return 0444;
break; break;
case octo:
return 0444;
default: default:
if (channel < priv->num_fans)
return 0444;
break; break;
} }
break; break;
case hwmon_power:
case hwmon_curr:
if (channel < priv->num_fans)
return 0444;
break;
case hwmon_in: case hwmon_in:
switch (priv->kind) { switch (priv->kind) {
case d5next: case d5next:
if (channel < 3) /* Special case to support +5V and +12V voltage sensors */
if (channel < priv->num_fans + 2)
return 0444; return 0444;
break; break;
case octo:
return 0444;
default: default:
if (channel < priv->num_fans)
return 0444;
break; break;
} }
break; break;
...@@ -406,16 +419,12 @@ static int aqc_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, ...@@ -406,16 +419,12 @@ static int aqc_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
*val = priv->power_input[channel]; *val = priv->power_input[channel];
break; break;
case hwmon_pwm: case hwmon_pwm:
switch (priv->kind) { if (priv->fan_ctrl_offsets) {
case octo: ret = aqc_get_ctrl_val(priv, priv->fan_ctrl_offsets[channel]);
ret = aqc_get_ctrl_val(priv, octo_ctrl_fan_offsets[channel]);
if (ret < 0) if (ret < 0)
return ret; return ret;
*val = aqc_percent_to_pwm(ret); *val = aqc_percent_to_pwm(ret);
break;
default:
break;
} }
break; break;
case hwmon_in: case hwmon_in:
...@@ -469,19 +478,15 @@ static int aqc_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, ...@@ -469,19 +478,15 @@ static int aqc_write(struct device *dev, enum hwmon_sensor_types type, u32 attr,
case hwmon_pwm: case hwmon_pwm:
switch (attr) { switch (attr) {
case hwmon_pwm_input: case hwmon_pwm_input:
switch (priv->kind) { if (priv->fan_ctrl_offsets) {
case octo:
pwm_value = aqc_pwm_to_percent(val); pwm_value = aqc_pwm_to_percent(val);
if (pwm_value < 0) if (pwm_value < 0)
return pwm_value; return pwm_value;
ret = aqc_set_ctrl_val(priv, octo_ctrl_fan_offsets[channel], ret = aqc_set_ctrl_val(priv, priv->fan_ctrl_offsets[channel],
pwm_value); pwm_value);
if (ret < 0) if (ret < 0)
return ret; return ret;
break;
default:
break;
} }
break; break;
default: default:
...@@ -576,76 +581,42 @@ static int aqc_raw_event(struct hid_device *hdev, struct hid_report *report, u8 ...@@ -576,76 +581,42 @@ static int aqc_raw_event(struct hid_device *hdev, struct hid_report *report, u8
priv->serial_number[1] = get_unaligned_be16(data + SERIAL_SECOND_PART); priv->serial_number[1] = get_unaligned_be16(data + SERIAL_SECOND_PART);
priv->firmware_version = get_unaligned_be16(data + FIRMWARE_VERSION); priv->firmware_version = get_unaligned_be16(data + FIRMWARE_VERSION);
/* Sensor readings */ /* Temperature sensor readings */
switch (priv->kind) { for (i = 0; i < priv->num_temp_sensors; i++) {
case d5next: sensor_value = get_unaligned_be16(data +
priv->power_cycles = get_unaligned_be32(data + D5NEXT_POWER_CYCLES); priv->temp_sensor_start_offset +
i * AQC_TEMP_SENSOR_SIZE);
priv->temp_input[0] = get_unaligned_be16(data + D5NEXT_COOLANT_TEMP) * 10; if (sensor_value == AQC_TEMP_SENSOR_DISCONNECTED)
priv->temp_input[i] = -ENODATA;
else
priv->temp_input[i] = sensor_value * 10;
}
priv->speed_input[0] = get_unaligned_be16(data + D5NEXT_PUMP_SPEED); /* Fan speed and related readings */
priv->speed_input[1] = get_unaligned_be16(data + D5NEXT_FAN_SPEED); for (i = 0; i < priv->num_fans; i++) {
priv->speed_input[i] =
get_unaligned_be16(data + priv->fan_sensor_offsets[i] + AQC_FAN_SPEED_OFFSET);
priv->power_input[i] =
get_unaligned_be16(data + priv->fan_sensor_offsets[i] +
AQC_FAN_POWER_OFFSET) * 10000;
priv->voltage_input[i] =
get_unaligned_be16(data + priv->fan_sensor_offsets[i] +
AQC_FAN_VOLTAGE_OFFSET) * 10;
priv->current_input[i] =
get_unaligned_be16(data + priv->fan_sensor_offsets[i] + AQC_FAN_CURRENT_OFFSET);
}
priv->power_input[0] = get_unaligned_be16(data + D5NEXT_PUMP_POWER) * 10000; if (priv->power_cycle_count_offset != 0)
priv->power_input[1] = get_unaligned_be16(data + D5NEXT_FAN_POWER) * 10000; priv->power_cycles = get_unaligned_be32(data + priv->power_cycle_count_offset);
priv->voltage_input[0] = get_unaligned_be16(data + D5NEXT_PUMP_VOLTAGE) * 10; /* Special-case sensor readings */
priv->voltage_input[1] = get_unaligned_be16(data + D5NEXT_FAN_VOLTAGE) * 10; switch (priv->kind) {
case d5next:
priv->voltage_input[2] = get_unaligned_be16(data + D5NEXT_5V_VOLTAGE) * 10; priv->voltage_input[2] = get_unaligned_be16(data + D5NEXT_5V_VOLTAGE) * 10;
priv->voltage_input[3] = get_unaligned_be16(data + D5NEXT_12V_VOLTAGE) * 10;
priv->current_input[0] = get_unaligned_be16(data + D5NEXT_PUMP_CURRENT);
priv->current_input[1] = get_unaligned_be16(data + D5NEXT_FAN_CURRENT);
break;
case farbwerk:
/* Temperature sensor readings */
for (i = 0; i < FARBWERK_NUM_SENSORS; i++) {
sensor_value = get_unaligned_be16(data + FARBWERK_SENSOR_START +
i * FARBWERK_SENSOR_SIZE);
if (sensor_value == FARBWERK_SENSOR_DISCONNECTED)
priv->temp_input[i] = -ENODATA;
else
priv->temp_input[i] = sensor_value * 10;
}
break;
case farbwerk360:
/* Temperature sensor readings */
for (i = 0; i < FARBWERK360_NUM_SENSORS; i++) {
sensor_value = get_unaligned_be16(data + FARBWERK360_SENSOR_START +
i * FARBWERK360_SENSOR_SIZE);
if (sensor_value == FARBWERK360_SENSOR_DISCONNECTED)
priv->temp_input[i] = -ENODATA;
else
priv->temp_input[i] = sensor_value * 10;
}
break; break;
case octo: case quadro:
priv->power_cycles = get_unaligned_be32(data + OCTO_POWER_CYCLES); priv->speed_input[4] = get_unaligned_be16(data + priv->flow_sensor_offset);
/* Fan speed and related readings */
for (i = 0; i < OCTO_NUM_FANS; i++) {
priv->speed_input[i] =
get_unaligned_be16(data + octo_sensor_fan_offsets[i] +
OCTO_FAN_SPEED_OFFSET);
priv->power_input[i] =
get_unaligned_be16(data + octo_sensor_fan_offsets[i] +
OCTO_FAN_POWER_OFFSET) * 10000;
priv->voltage_input[i] =
get_unaligned_be16(data + octo_sensor_fan_offsets[i] +
OCTO_FAN_VOLTAGE_OFFSET) * 10;
priv->current_input[i] =
get_unaligned_be16(data + octo_sensor_fan_offsets[i] +
OCTO_FAN_CURRENT_OFFSET);
}
/* Temperature sensor readings */
for (i = 0; i < OCTO_NUM_SENSORS; i++) {
sensor_value = get_unaligned_be16(data + OCTO_SENSOR_START +
i * OCTO_SENSOR_SIZE);
if (sensor_value == OCTO_SENSOR_DISCONNECTED)
priv->temp_input[i] = -ENODATA;
else
priv->temp_input[i] = sensor_value * 10;
}
break; break;
default: default:
break; break;
...@@ -699,14 +670,8 @@ static void aqc_debugfs_init(struct aqc_data *priv) ...@@ -699,14 +670,8 @@ static void aqc_debugfs_init(struct aqc_data *priv)
debugfs_create_file("serial_number", 0444, priv->debugfs, priv, &serial_number_fops); debugfs_create_file("serial_number", 0444, priv->debugfs, priv, &serial_number_fops);
debugfs_create_file("firmware_version", 0444, priv->debugfs, priv, &firmware_version_fops); debugfs_create_file("firmware_version", 0444, priv->debugfs, priv, &firmware_version_fops);
switch (priv->kind) { if (priv->power_cycle_count_offset != 0)
case d5next:
case octo:
debugfs_create_file("power_cycles", 0444, priv->debugfs, priv, &power_cycles_fops); debugfs_create_file("power_cycles", 0444, priv->debugfs, priv, &power_cycles_fops);
break;
default:
break;
}
} }
#else #else
...@@ -747,6 +712,14 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -747,6 +712,14 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
case USB_PRODUCT_ID_D5NEXT: case USB_PRODUCT_ID_D5NEXT:
priv->kind = d5next; priv->kind = d5next;
priv->num_fans = D5NEXT_NUM_FANS;
priv->fan_sensor_offsets = d5next_sensor_fan_offsets;
priv->fan_ctrl_offsets = d5next_ctrl_fan_offsets;
priv->num_temp_sensors = D5NEXT_NUM_SENSORS;
priv->temp_sensor_start_offset = D5NEXT_COOLANT_TEMP;
priv->power_cycle_count_offset = D5NEXT_POWER_CYCLES;
priv->buffer_size = D5NEXT_CTRL_REPORT_SIZE;
priv->temp_label = label_d5next_temp; priv->temp_label = label_d5next_temp;
priv->speed_label = label_d5next_speeds; priv->speed_label = label_d5next_speeds;
priv->power_label = label_d5next_power; priv->power_label = label_d5next_power;
...@@ -756,19 +729,29 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -756,19 +729,29 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
case USB_PRODUCT_ID_FARBWERK: case USB_PRODUCT_ID_FARBWERK:
priv->kind = farbwerk; priv->kind = farbwerk;
priv->num_fans = 0;
priv->num_temp_sensors = FARBWERK_NUM_SENSORS;
priv->temp_sensor_start_offset = FARBWERK_SENSOR_START;
priv->temp_label = label_temp_sensors; priv->temp_label = label_temp_sensors;
break; break;
case USB_PRODUCT_ID_FARBWERK360: case USB_PRODUCT_ID_FARBWERK360:
priv->kind = farbwerk360; priv->kind = farbwerk360;
priv->num_fans = 0;
priv->num_temp_sensors = FARBWERK360_NUM_SENSORS;
priv->temp_sensor_start_offset = FARBWERK360_SENSOR_START;
priv->temp_label = label_temp_sensors; priv->temp_label = label_temp_sensors;
break; break;
case USB_PRODUCT_ID_OCTO: case USB_PRODUCT_ID_OCTO:
priv->kind = octo; priv->kind = octo;
priv->num_fans = OCTO_NUM_FANS;
priv->fan_sensor_offsets = octo_sensor_fan_offsets;
priv->fan_ctrl_offsets = octo_ctrl_fan_offsets;
priv->num_temp_sensors = OCTO_NUM_SENSORS;
priv->temp_sensor_start_offset = OCTO_SENSOR_START;
priv->power_cycle_count_offset = OCTO_POWER_CYCLES;
priv->buffer_size = OCTO_CTRL_REPORT_SIZE; priv->buffer_size = OCTO_CTRL_REPORT_SIZE;
priv->checksum_start = OCTO_CTRL_REPORT_CHECKSUM_START;
priv->checksum_length = OCTO_CTRL_REPORT_CHECKSUM_LENGTH;
priv->checksum_offset = OCTO_CTRL_REPORT_CHECKSUM_OFFSET;
priv->temp_label = label_temp_sensors; priv->temp_label = label_temp_sensors;
priv->speed_label = label_fan_speed; priv->speed_label = label_fan_speed;
...@@ -776,10 +759,34 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -776,10 +759,34 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
priv->voltage_label = label_fan_voltage; priv->voltage_label = label_fan_voltage;
priv->current_label = label_fan_current; priv->current_label = label_fan_current;
break; break;
case USB_PRODUCT_ID_QUADRO:
priv->kind = quadro;
priv->num_fans = QUADRO_NUM_FANS;
priv->fan_sensor_offsets = quadro_sensor_fan_offsets;
priv->fan_ctrl_offsets = quadro_ctrl_fan_offsets;
priv->num_temp_sensors = QUADRO_NUM_SENSORS;
priv->temp_sensor_start_offset = QUADRO_SENSOR_START;
priv->power_cycle_count_offset = QUADRO_POWER_CYCLES;
priv->buffer_size = QUADRO_CTRL_REPORT_SIZE;
priv->flow_sensor_offset = QUADRO_FLOW_SENSOR_OFFSET;
priv->temp_label = label_temp_sensors;
priv->speed_label = label_quadro_speeds;
priv->power_label = label_fan_power;
priv->voltage_label = label_fan_voltage;
priv->current_label = label_fan_current;
break;
default: default:
break; break;
} }
if (priv->buffer_size != 0) {
priv->checksum_start = 0x01;
priv->checksum_length = priv->buffer_size - 3;
priv->checksum_offset = priv->buffer_size - 2;
}
priv->name = aqc_device_names[priv->kind]; priv->name = aqc_device_names[priv->kind];
priv->buffer = devm_kzalloc(&hdev->dev, priv->buffer_size, GFP_KERNEL); priv->buffer = devm_kzalloc(&hdev->dev, priv->buffer_size, GFP_KERNEL);
...@@ -825,6 +832,7 @@ static const struct hid_device_id aqc_table[] = { ...@@ -825,6 +832,7 @@ static const struct hid_device_id aqc_table[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_FARBWERK) }, { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_FARBWERK) },
{ HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_FARBWERK360) }, { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_FARBWERK360) },
{ HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_OCTO) }, { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_OCTO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_QUADRO) },
{ } { }
}; };
......
...@@ -159,7 +159,7 @@ ...@@ -159,7 +159,7 @@
* 11: reserved. * 11: reserved.
*/ */
#define M_TACH_MODE 0x02 /* 10b */ #define M_TACH_MODE 0x02 /* 10b */
#define M_TACH_UNIT 0x0210 #define M_TACH_UNIT 0x0420
#define INIT_FAN_CTRL 0xFF #define INIT_FAN_CTRL 0xFF
/* How long we sleep in us while waiting for an RPM result. */ /* How long we sleep in us while waiting for an RPM result. */
......
...@@ -54,6 +54,10 @@ static char *mutex_path_override; ...@@ -54,6 +54,10 @@ static char *mutex_path_override;
/* ACPI mutex for locking access to the EC for the firmware */ /* ACPI mutex for locking access to the EC for the firmware */
#define ASUS_HW_ACCESS_MUTEX_ASMX "\\AMW0.ASMX" #define ASUS_HW_ACCESS_MUTEX_ASMX "\\AMW0.ASMX"
#define ASUS_HW_ACCESS_MUTEX_RMTW_ASMX "\\RMTW.ASMX"
#define ASUS_HW_ACCESS_MUTEX_SB_PCI0_SBRG_SIO1_MUT0 "\\_SB_.PCI0.SBRG.SIO1.MUT0"
#define MAX_IDENTICAL_BOARD_VARIATIONS 3 #define MAX_IDENTICAL_BOARD_VARIATIONS 3
/* Moniker for the ACPI global lock (':' is not allowed in ASL identifiers) */ /* Moniker for the ACPI global lock (':' is not allowed in ASL identifiers) */
...@@ -119,6 +123,18 @@ enum ec_sensors { ...@@ -119,6 +123,18 @@ enum ec_sensors {
ec_sensor_temp_water_in, ec_sensor_temp_water_in,
/* "Water_Out" temperature sensor reading [℃] */ /* "Water_Out" temperature sensor reading [℃] */
ec_sensor_temp_water_out, ec_sensor_temp_water_out,
/* "Water_Block_In" temperature sensor reading [℃] */
ec_sensor_temp_water_block_in,
/* "Water_Block_Out" temperature sensor reading [℃] */
ec_sensor_temp_water_block_out,
/* "T_sensor_2" temperature sensor reading [℃] */
ec_sensor_temp_t_sensor_2,
/* "Extra_1" temperature sensor reading [℃] */
ec_sensor_temp_sensor_extra_1,
/* "Extra_2" temperature sensor reading [℃] */
ec_sensor_temp_sensor_extra_2,
/* "Extra_3" temperature sensor reading [℃] */
ec_sensor_temp_sensor_extra_3,
}; };
#define SENSOR_TEMP_CHIPSET BIT(ec_sensor_temp_chipset) #define SENSOR_TEMP_CHIPSET BIT(ec_sensor_temp_chipset)
...@@ -134,11 +150,19 @@ enum ec_sensors { ...@@ -134,11 +150,19 @@ enum ec_sensors {
#define SENSOR_CURR_CPU BIT(ec_sensor_curr_cpu) #define SENSOR_CURR_CPU BIT(ec_sensor_curr_cpu)
#define SENSOR_TEMP_WATER_IN BIT(ec_sensor_temp_water_in) #define SENSOR_TEMP_WATER_IN BIT(ec_sensor_temp_water_in)
#define SENSOR_TEMP_WATER_OUT BIT(ec_sensor_temp_water_out) #define SENSOR_TEMP_WATER_OUT BIT(ec_sensor_temp_water_out)
#define SENSOR_TEMP_WATER_BLOCK_IN BIT(ec_sensor_temp_water_block_in)
#define SENSOR_TEMP_WATER_BLOCK_OUT BIT(ec_sensor_temp_water_block_out)
#define SENSOR_TEMP_T_SENSOR_2 BIT(ec_sensor_temp_t_sensor_2)
#define SENSOR_TEMP_SENSOR_EXTRA_1 BIT(ec_sensor_temp_sensor_extra_1)
#define SENSOR_TEMP_SENSOR_EXTRA_2 BIT(ec_sensor_temp_sensor_extra_2)
#define SENSOR_TEMP_SENSOR_EXTRA_3 BIT(ec_sensor_temp_sensor_extra_3)
enum board_family { enum board_family {
family_unknown, family_unknown,
family_amd_400_series, family_amd_400_series,
family_amd_500_series, family_amd_500_series,
family_intel_300_series,
family_intel_600_series
}; };
/* All the known sensors for ASUS EC controllers */ /* All the known sensors for ASUS EC controllers */
...@@ -195,12 +219,53 @@ static const struct ec_sensor_info sensors_family_amd_500[] = { ...@@ -195,12 +219,53 @@ static const struct ec_sensor_info sensors_family_amd_500[] = {
EC_SENSOR("Water_In", hwmon_temp, 1, 0x01, 0x00), EC_SENSOR("Water_In", hwmon_temp, 1, 0x01, 0x00),
[ec_sensor_temp_water_out] = [ec_sensor_temp_water_out] =
EC_SENSOR("Water_Out", hwmon_temp, 1, 0x01, 0x01), EC_SENSOR("Water_Out", hwmon_temp, 1, 0x01, 0x01),
[ec_sensor_temp_water_block_in] =
EC_SENSOR("Water_Block_In", hwmon_temp, 1, 0x01, 0x02),
[ec_sensor_temp_water_block_out] =
EC_SENSOR("Water_Block_Out", hwmon_temp, 1, 0x01, 0x03),
[ec_sensor_temp_sensor_extra_1] =
EC_SENSOR("Extra_1", hwmon_temp, 1, 0x01, 0x09),
[ec_sensor_temp_t_sensor_2] =
EC_SENSOR("T_sensor_2", hwmon_temp, 1, 0x01, 0x0a),
[ec_sensor_temp_sensor_extra_2] =
EC_SENSOR("Extra_2", hwmon_temp, 1, 0x01, 0x0b),
[ec_sensor_temp_sensor_extra_3] =
EC_SENSOR("Extra_3", hwmon_temp, 1, 0x01, 0x0c),
};
static const struct ec_sensor_info sensors_family_intel_300[] = {
[ec_sensor_temp_chipset] =
EC_SENSOR("Chipset", hwmon_temp, 1, 0x00, 0x3a),
[ec_sensor_temp_cpu] = EC_SENSOR("CPU", hwmon_temp, 1, 0x00, 0x3b),
[ec_sensor_temp_mb] =
EC_SENSOR("Motherboard", hwmon_temp, 1, 0x00, 0x3c),
[ec_sensor_temp_t_sensor] =
EC_SENSOR("T_Sensor", hwmon_temp, 1, 0x00, 0x3d),
[ec_sensor_temp_vrm] = EC_SENSOR("VRM", hwmon_temp, 1, 0x00, 0x3e),
[ec_sensor_fan_cpu_opt] =
EC_SENSOR("CPU_Opt", hwmon_fan, 2, 0x00, 0xb0),
[ec_sensor_fan_vrm_hs] = EC_SENSOR("VRM HS", hwmon_fan, 2, 0x00, 0xb2),
[ec_sensor_fan_water_flow] =
EC_SENSOR("Water_Flow", hwmon_fan, 2, 0x00, 0xbc),
[ec_sensor_temp_water_in] =
EC_SENSOR("Water_In", hwmon_temp, 1, 0x01, 0x00),
[ec_sensor_temp_water_out] =
EC_SENSOR("Water_Out", hwmon_temp, 1, 0x01, 0x01),
};
static const struct ec_sensor_info sensors_family_intel_600[] = {
[ec_sensor_temp_t_sensor] =
EC_SENSOR("T_Sensor", hwmon_temp, 1, 0x00, 0x3d),
[ec_sensor_temp_vrm] = EC_SENSOR("VRM", hwmon_temp, 1, 0x00, 0x3e),
}; };
/* Shortcuts for common combinations */ /* Shortcuts for common combinations */
#define SENSOR_SET_TEMP_CHIPSET_CPU_MB \ #define SENSOR_SET_TEMP_CHIPSET_CPU_MB \
(SENSOR_TEMP_CHIPSET | SENSOR_TEMP_CPU | SENSOR_TEMP_MB) (SENSOR_TEMP_CHIPSET | SENSOR_TEMP_CPU | SENSOR_TEMP_MB)
#define SENSOR_SET_TEMP_WATER (SENSOR_TEMP_WATER_IN | SENSOR_TEMP_WATER_OUT) #define SENSOR_SET_TEMP_WATER (SENSOR_TEMP_WATER_IN | SENSOR_TEMP_WATER_OUT)
#define SENSOR_SET_WATER_BLOCK \
(SENSOR_TEMP_WATER_BLOCK_IN | SENSOR_TEMP_WATER_BLOCK_OUT)
struct ec_board_info { struct ec_board_info {
const char *board_names[MAX_IDENTICAL_BOARD_VARIATIONS]; const char *board_names[MAX_IDENTICAL_BOARD_VARIATIONS];
...@@ -272,6 +337,18 @@ static const struct ec_board_info board_info[] = { ...@@ -272,6 +337,18 @@ static const struct ec_board_info board_info[] = {
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
.family = family_amd_500_series, .family = family_amd_500_series,
}, },
{
.board_names = {
"ROG MAXIMUS XI HERO",
"ROG MAXIMUS XI HERO (WI-FI)",
},
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
SENSOR_TEMP_T_SENSOR |
SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER |
SENSOR_FAN_CPU_OPT | SENSOR_FAN_WATER_FLOW,
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
.family = family_intel_300_series,
},
{ {
.board_names = {"ROG CROSSHAIR VIII IMPACT"}, .board_names = {"ROG CROSSHAIR VIII IMPACT"},
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
...@@ -324,12 +401,31 @@ static const struct ec_board_info board_info[] = { ...@@ -324,12 +401,31 @@ static const struct ec_board_info board_info[] = {
}, },
{ {
.board_names = {"ROG STRIX X570-I GAMING"}, .board_names = {"ROG STRIX X570-I GAMING"},
.sensors = SENSOR_TEMP_T_SENSOR | SENSOR_FAN_VRM_HS | .sensors = SENSOR_TEMP_CHIPSET | SENSOR_TEMP_VRM |
SENSOR_FAN_CHIPSET | SENSOR_CURR_CPU | SENSOR_TEMP_T_SENSOR |
SENSOR_IN_CPU_CORE, SENSOR_FAN_VRM_HS | SENSOR_FAN_CHIPSET |
SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE,
.mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
.family = family_amd_500_series, .family = family_amd_500_series,
}, },
{
.board_names = {"ROG STRIX Z690-A GAMING WIFI D4"},
.sensors = SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM,
.mutex_path = ASUS_HW_ACCESS_MUTEX_RMTW_ASMX,
.family = family_intel_600_series,
},
{
.board_names = {"ROG ZENITH II EXTREME"},
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_T_SENSOR |
SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER |
SENSOR_FAN_CPU_OPT | SENSOR_FAN_CHIPSET | SENSOR_FAN_VRM_HS |
SENSOR_FAN_WATER_FLOW | SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE |
SENSOR_SET_WATER_BLOCK |
SENSOR_TEMP_T_SENSOR_2 | SENSOR_TEMP_SENSOR_EXTRA_1 |
SENSOR_TEMP_SENSOR_EXTRA_2 | SENSOR_TEMP_SENSOR_EXTRA_3,
.mutex_path = ASUS_HW_ACCESS_MUTEX_SB_PCI0_SBRG_SIO1_MUT0,
.family = family_amd_500_series,
},
{} {}
}; };
...@@ -799,6 +895,12 @@ static int __init asus_ec_probe(struct platform_device *pdev) ...@@ -799,6 +895,12 @@ static int __init asus_ec_probe(struct platform_device *pdev)
case family_amd_500_series: case family_amd_500_series:
ec_data->sensors_info = sensors_family_amd_500; ec_data->sensors_info = sensors_family_amd_500;
break; break;
case family_intel_300_series:
ec_data->sensors_info = sensors_family_intel_300;
break;
case family_intel_600_series:
ec_data->sensors_info = sensors_family_intel_600;
break;
default: default:
dev_err(dev, "Unknown board family: %d", dev_err(dev, "Unknown board family: %d",
ec_data->board_info->family); ec_data->board_info->family);
......
...@@ -514,22 +514,20 @@ static int asus_wmi_configure_sensor_setup(struct device *dev, ...@@ -514,22 +514,20 @@ static int asus_wmi_configure_sensor_setup(struct device *dev,
int i, idx; int i, idx;
int err; int err;
temp_sensor = devm_kcalloc(dev, 1, sizeof(*temp_sensor), GFP_KERNEL);
if (!temp_sensor)
return -ENOMEM;
for (i = 0; i < sensor_data->wmi.sensor_count; i++) { for (i = 0; i < sensor_data->wmi.sensor_count; i++) {
err = asus_wmi_sensor_info(i, temp_sensor); struct asus_wmi_sensor_info sensor;
err = asus_wmi_sensor_info(i, &sensor);
if (err) if (err)
return err; return err;
switch (temp_sensor->data_type) { switch (sensor.data_type) {
case TEMPERATURE_C: case TEMPERATURE_C:
case VOLTAGE: case VOLTAGE:
case CURRENT: case CURRENT:
case FAN_RPM: case FAN_RPM:
case WATER_FLOW: case WATER_FLOW:
type = asus_data_types[temp_sensor->data_type]; type = asus_data_types[sensor.data_type];
if (!nr_count[type]) if (!nr_count[type])
nr_types++; nr_types++;
nr_count[type]++; nr_count[type]++;
......
...@@ -130,7 +130,7 @@ struct smm_regs { ...@@ -130,7 +130,7 @@ struct smm_regs {
unsigned int edx; unsigned int edx;
unsigned int esi; unsigned int esi;
unsigned int edi; unsigned int edi;
} __packed; };
static const char * const temp_labels[] = { static const char * const temp_labels[] = {
"CPU", "CPU",
...@@ -175,77 +175,35 @@ static int i8k_smm_func(void *par) ...@@ -175,77 +175,35 @@ static int i8k_smm_func(void *par)
struct smm_regs *regs = par; struct smm_regs *regs = par;
int eax = regs->eax; int eax = regs->eax;
int ebx = regs->ebx; int ebx = regs->ebx;
unsigned char carry;
long long duration; long long duration;
int rc;
/* SMM requires CPU 0 */ /* SMM requires CPU 0 */
if (smp_processor_id() != 0) if (smp_processor_id() != 0)
return -EBUSY; return -EBUSY;
#if defined(CONFIG_X86_64) asm volatile("out %%al,$0xb2\n\t"
asm volatile("pushq %%rax\n\t" "out %%al,$0x84\n\t"
"movl 0(%%rax),%%edx\n\t" "setc %0\n"
"pushq %%rdx\n\t" : "=mr" (carry),
"movl 4(%%rax),%%ebx\n\t" "+a" (regs->eax),
"movl 8(%%rax),%%ecx\n\t" "+b" (regs->ebx),
"movl 12(%%rax),%%edx\n\t" "+c" (regs->ecx),
"movl 16(%%rax),%%esi\n\t" "+d" (regs->edx),
"movl 20(%%rax),%%edi\n\t" "+S" (regs->esi),
"popq %%rax\n\t" "+D" (regs->edi));
"out %%al,$0xb2\n\t"
"out %%al,$0x84\n\t"
"xchgq %%rax,(%%rsp)\n\t"
"movl %%ebx,4(%%rax)\n\t"
"movl %%ecx,8(%%rax)\n\t"
"movl %%edx,12(%%rax)\n\t"
"movl %%esi,16(%%rax)\n\t"
"movl %%edi,20(%%rax)\n\t"
"popq %%rdx\n\t"
"movl %%edx,0(%%rax)\n\t"
"pushfq\n\t"
"popq %%rax\n\t"
"andl $1,%%eax\n"
: "=a"(rc)
: "a"(regs)
: "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
#else
asm volatile("pushl %%eax\n\t"
"movl 0(%%eax),%%edx\n\t"
"push %%edx\n\t"
"movl 4(%%eax),%%ebx\n\t"
"movl 8(%%eax),%%ecx\n\t"
"movl 12(%%eax),%%edx\n\t"
"movl 16(%%eax),%%esi\n\t"
"movl 20(%%eax),%%edi\n\t"
"popl %%eax\n\t"
"out %%al,$0xb2\n\t"
"out %%al,$0x84\n\t"
"xchgl %%eax,(%%esp)\n\t"
"movl %%ebx,4(%%eax)\n\t"
"movl %%ecx,8(%%eax)\n\t"
"movl %%edx,12(%%eax)\n\t"
"movl %%esi,16(%%eax)\n\t"
"movl %%edi,20(%%eax)\n\t"
"popl %%edx\n\t"
"movl %%edx,0(%%eax)\n\t"
"lahf\n\t"
"shrl $8,%%eax\n\t"
"andl $1,%%eax\n"
: "=a"(rc)
: "a"(regs)
: "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
#endif
if (rc != 0 || (regs->eax & 0xffff) == 0xffff || regs->eax == eax)
rc = -EINVAL;
duration = ktime_us_delta(ktime_get(), calltime); duration = ktime_us_delta(ktime_get(), calltime);
pr_debug("smm(0x%.4x 0x%.4x) = 0x%.4x (took %7lld usecs)\n", eax, ebx, pr_debug("smm(0x%.4x 0x%.4x) = 0x%.4x carry: %d (took %7lld usecs)\n",
(rc ? 0xffff : regs->eax & 0xffff), duration); eax, ebx, regs->eax & 0xffff, carry, duration);
if (duration > DELL_SMM_MAX_DURATION) if (duration > DELL_SMM_MAX_DURATION)
pr_warn_once("SMM call took %lld usecs!\n", duration); pr_warn_once("SMM call took %lld usecs!\n", duration);
return rc; if (carry || (regs->eax & 0xffff) == 0xffff || regs->eax == eax)
return -EINVAL;
return 0;
} }
/* /*
...@@ -1131,6 +1089,13 @@ static const struct i8k_config_data i8k_config_data[] __initconst = { ...@@ -1131,6 +1089,13 @@ static const struct i8k_config_data i8k_config_data[] __initconst = {
}; };
static const struct dmi_system_id i8k_dmi_table[] __initconst = { static const struct dmi_system_id i8k_dmi_table[] __initconst = {
{
.ident = "Dell G5 5590",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "G5 5590"),
},
},
{ {
.ident = "Dell Inspiron", .ident = "Dell Inspiron",
.matches = { .matches = {
...@@ -1365,6 +1330,14 @@ static const struct dmi_system_id i8k_whitelist_fan_control[] __initconst = { ...@@ -1365,6 +1330,14 @@ static const struct dmi_system_id i8k_whitelist_fan_control[] __initconst = {
}, },
.driver_data = (void *)&i8k_fan_control_data[I8K_FAN_34A3_35A3], .driver_data = (void *)&i8k_fan_control_data[I8K_FAN_34A3_35A3],
}, },
{
.ident = "Dell XPS 13 7390",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "XPS 13 7390"),
},
.driver_data = (void *)&i8k_fan_control_data[I8K_FAN_34A3_35A3],
},
{ } { }
}; };
......
...@@ -621,3 +621,4 @@ module_exit(drivetemp_exit); ...@@ -621,3 +621,4 @@ module_exit(drivetemp_exit);
MODULE_AUTHOR("Guenter Roeck <linus@roeck-us.net>"); MODULE_AUTHOR("Guenter Roeck <linus@roeck-us.net>");
MODULE_DESCRIPTION("Hard drive temperature monitor"); MODULE_DESCRIPTION("Hard drive temperature monitor");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:drivetemp");
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#define SIO_F81768D_ID 0x1210 /* Chipset ID */ #define SIO_F81768D_ID 0x1210 /* Chipset ID */
#define SIO_F81865_ID 0x0704 /* Chipset ID */ #define SIO_F81865_ID 0x0704 /* Chipset ID */
#define SIO_F81866_ID 0x1010 /* Chipset ID */ #define SIO_F81866_ID 0x1010 /* Chipset ID */
#define SIO_F71858AD_ID 0x0903 /* Chipset ID */
#define SIO_F81966_ID 0x1502 /* Chipset ID */ #define SIO_F81966_ID 0x1502 /* Chipset ID */
#define REGION_LENGTH 8 #define REGION_LENGTH 8
...@@ -2638,6 +2639,7 @@ static int __init f71882fg_find(int sioaddr, struct f71882fg_sio_data *sio_data) ...@@ -2638,6 +2639,7 @@ static int __init f71882fg_find(int sioaddr, struct f71882fg_sio_data *sio_data)
sio_data->type = f71808a; sio_data->type = f71808a;
break; break;
case SIO_F71858_ID: case SIO_F71858_ID:
case SIO_F71858AD_ID:
sio_data->type = f71858fg; sio_data->type = f71858fg;
break; break;
case SIO_F71862_ID: case SIO_F71862_ID:
......
...@@ -269,10 +269,13 @@ gsc_hwmon_get_devtree_pdata(struct device *dev) ...@@ -269,10 +269,13 @@ gsc_hwmon_get_devtree_pdata(struct device *dev)
/* fan controller base address */ /* fan controller base address */
fan = of_find_compatible_node(dev->parent->of_node, NULL, "gw,gsc-fan"); fan = of_find_compatible_node(dev->parent->of_node, NULL, "gw,gsc-fan");
if (fan && of_property_read_u32(fan, "reg", &pdata->fan_base)) { if (fan && of_property_read_u32(fan, "reg", &pdata->fan_base)) {
of_node_put(fan);
dev_err(dev, "fan node without base\n"); dev_err(dev, "fan node without base\n");
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
of_node_put(fan);
/* allocate structures for channels and count instances of each type */ /* allocate structures for channels and count instances of each type */
device_for_each_child_node(dev, child) { device_for_each_child_node(dev, child) {
if (fwnode_property_read_string(child, "label", &ch->name)) { if (fwnode_property_read_string(child, "label", &ch->name)) {
......
...@@ -11,7 +11,8 @@ ...@@ -11,7 +11,8 @@
* which contains this code, we don't worry about the wasted space. * which contains this code, we don't worry about the wasted space.
*/ */
#include <linux/kernel.h> #include <linux/minmax.h>
#include <linux/types.h>
/* straight from the datasheet */ /* straight from the datasheet */
#define LM75_TEMP_MIN (-55000) #define LM75_TEMP_MIN (-55000)
......
此差异已折叠。
此差异已折叠。
...@@ -1083,6 +1083,7 @@ static const char * const asus_wmi_boards[] = { ...@@ -1083,6 +1083,7 @@ static const char * const asus_wmi_boards[] = {
"TUF GAMING B550M-PLUS", "TUF GAMING B550M-PLUS",
"TUF GAMING B550M-PLUS (WI-FI)", "TUF GAMING B550M-PLUS (WI-FI)",
"TUF GAMING B550-PLUS", "TUF GAMING B550-PLUS",
"TUF GAMING B550-PLUS WIFI II",
"TUF GAMING B550-PRO", "TUF GAMING B550-PRO",
"TUF GAMING X570-PLUS", "TUF GAMING X570-PLUS",
"TUF GAMING X570-PLUS (WI-FI)", "TUF GAMING X570-PLUS (WI-FI)",
...@@ -1200,10 +1201,8 @@ static int __init sensors_nct6775_platform_init(void) ...@@ -1200,10 +1201,8 @@ static int __init sensors_nct6775_platform_init(void)
exit_device_put: exit_device_put:
platform_device_put(pdev[i]); platform_device_put(pdev[i]);
exit_device_unregister: exit_device_unregister:
while (--i >= 0) { while (i--)
if (pdev[i]) platform_device_unregister(pdev[i]);
platform_device_unregister(pdev[i]);
}
exit_unregister: exit_unregister:
platform_driver_unregister(&nct6775_driver); platform_driver_unregister(&nct6775_driver);
return err; return err;
...@@ -1213,10 +1212,8 @@ static void __exit sensors_nct6775_platform_exit(void) ...@@ -1213,10 +1212,8 @@ static void __exit sensors_nct6775_platform_exit(void)
{ {
int i; int i;
for (i = 0; i < ARRAY_SIZE(pdev); i++) { for (i = 0; i < ARRAY_SIZE(pdev); i++)
if (pdev[i]) platform_device_unregister(pdev[i]);
platform_device_unregister(pdev[i]);
}
platform_driver_unregister(&nct6775_driver); platform_driver_unregister(&nct6775_driver);
} }
......
...@@ -729,18 +729,14 @@ static ssize_t occ_show_extended(struct device *dev, ...@@ -729,18 +729,14 @@ static ssize_t occ_show_extended(struct device *dev,
rc = sysfs_emit(buf, "%u", rc = sysfs_emit(buf, "%u",
get_unaligned_be32(&extn->sensor_id)); get_unaligned_be32(&extn->sensor_id));
} else { } else {
rc = sysfs_emit(buf, "%02x%02x%02x%02x\n", rc = sysfs_emit(buf, "%4phN\n", extn->name);
extn->name[0], extn->name[1],
extn->name[2], extn->name[3]);
} }
break; break;
case 1: case 1:
rc = sysfs_emit(buf, "%02x\n", extn->flags); rc = sysfs_emit(buf, "%02x\n", extn->flags);
break; break;
case 2: case 2:
rc = sysfs_emit(buf, "%02x%02x%02x%02x%02x%02x\n", rc = sysfs_emit(buf, "%6phN\n", extn->data);
extn->data[0], extn->data[1], extn->data[2],
extn->data[3], extn->data[4], extn->data[5]);
break; break;
default: default:
return -EINVAL; return -EINVAL;
......
...@@ -55,8 +55,7 @@ static bool p9_sbe_occ_save_ffdc(struct p9_sbe_occ *ctx, const void *resp, ...@@ -55,8 +55,7 @@ static bool p9_sbe_occ_save_ffdc(struct p9_sbe_occ *ctx, const void *resp,
mutex_lock(&ctx->sbe_error_lock); mutex_lock(&ctx->sbe_error_lock);
if (!ctx->sbe_error) { if (!ctx->sbe_error) {
if (resp_len > ctx->ffdc_size) { if (resp_len > ctx->ffdc_size) {
if (ctx->ffdc) kvfree(ctx->ffdc);
kvfree(ctx->ffdc);
ctx->ffdc = kvmalloc(resp_len, GFP_KERNEL); ctx->ffdc = kvmalloc(resp_len, GFP_KERNEL);
if (!ctx->ffdc) { if (!ctx->ffdc) {
ctx->ffdc_len = 0; ctx->ffdc_len = 0;
...@@ -170,8 +169,7 @@ static int p9_sbe_occ_remove(struct platform_device *pdev) ...@@ -170,8 +169,7 @@ static int p9_sbe_occ_remove(struct platform_device *pdev)
ctx->sbe = NULL; ctx->sbe = NULL;
occ_shutdown(occ); occ_shutdown(occ);
if (ctx->ffdc) kvfree(ctx->ffdc);
kvfree(ctx->ffdc);
return 0; return 0;
} }
......
...@@ -181,6 +181,15 @@ config SENSORS_LM25066_REGULATOR ...@@ -181,6 +181,15 @@ config SENSORS_LM25066_REGULATOR
If you say yes here you get regulator support for National If you say yes here you get regulator support for National
Semiconductor LM25066, LM5064, and LM5066. Semiconductor LM25066, LM5064, and LM5066.
config SENSORS_LT7182S
tristate "Analog Devices LT7182S"
help
If you say yes here you get hardware monitoring support for Analog
Devices LT7182S.
This driver can also be built as a module. If so, the module will
be called lt7182s.
config SENSORS_LTC2978 config SENSORS_LTC2978
tristate "Linear Technologies LTC2978 and compatibles" tristate "Linear Technologies LTC2978 and compatibles"
help help
......
...@@ -20,6 +20,7 @@ obj-$(CONFIG_SENSORS_IR38064) += ir38064.o ...@@ -20,6 +20,7 @@ obj-$(CONFIG_SENSORS_IR38064) += ir38064.o
obj-$(CONFIG_SENSORS_IRPS5401) += irps5401.o obj-$(CONFIG_SENSORS_IRPS5401) += irps5401.o
obj-$(CONFIG_SENSORS_ISL68137) += isl68137.o obj-$(CONFIG_SENSORS_ISL68137) += isl68137.o
obj-$(CONFIG_SENSORS_LM25066) += lm25066.o obj-$(CONFIG_SENSORS_LM25066) += lm25066.o
obj-$(CONFIG_SENSORS_LT7182S) += lt7182s.o
obj-$(CONFIG_SENSORS_LTC2978) += ltc2978.o obj-$(CONFIG_SENSORS_LTC2978) += ltc2978.o
obj-$(CONFIG_SENSORS_LTC3815) += ltc3815.o obj-$(CONFIG_SENSORS_LTC3815) += ltc3815.o
obj-$(CONFIG_SENSORS_MAX15301) += max15301.o obj-$(CONFIG_SENSORS_MAX15301) += max15301.o
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册