Commit 64ae88ff authored by Linus Torvalds's avatar 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
  ...
parents 530c28df cdbe34da
...@@ -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
......
This diff is collapsed.
...@@ -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)
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Reworked by Sven Schuchmann <schuchmann@schleissheimer.de> * Reworked by Sven Schuchmann <schuchmann@schleissheimer.de>
* DT support added by Clemens Gruber <clemens.gruber@pqgruber.com> * DT support added by Clemens Gruber <clemens.gruber@pqgruber.com>
* *
* This driver export the value of analog input voltage to sysfs, the * This driver exports the value of analog input voltage to sysfs, the
* voltage unit is mV. Through the sysfs interface, lm-sensors tool * voltage unit is mV. Through the sysfs interface, lm-sensors tool
* can also display the input voltage. * can also display the input voltage.
*/ */
...@@ -45,19 +45,29 @@ enum chips { ...@@ -45,19 +45,29 @@ enum chips {
* Client data (each client gets its own) * Client data (each client gets its own)
*/ */
struct mcp3021_data { struct mcp3021_data {
struct device *hwmon_dev; struct i2c_client *client;
u32 vdd; /* supply and reference voltage in millivolt */ u32 vdd; /* supply and reference voltage in millivolt */
u16 sar_shift; u16 sar_shift;
u16 sar_mask; u16 sar_mask;
u8 output_res; u8 output_res;
}; };
static int mcp3021_read16(struct i2c_client *client) static inline u16 volts_from_reg(struct mcp3021_data *data, u16 val)
{ {
struct mcp3021_data *data = i2c_get_clientdata(client); return DIV_ROUND_CLOSEST(data->vdd * val, 1 << data->output_res);
int ret; }
u16 reg;
static int mcp3021_read(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long *val)
{
struct mcp3021_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
__be16 buf; __be16 buf;
u16 reg;
int ret;
if (type != hwmon_in)
return -EOPNOTSUPP;
ret = i2c_master_recv(client, (char *)&buf, 2); ret = i2c_master_recv(client, (char *)&buf, 2);
if (ret < 0) if (ret < 0)
...@@ -74,39 +84,46 @@ static int mcp3021_read16(struct i2c_client *client) ...@@ -74,39 +84,46 @@ static int mcp3021_read16(struct i2c_client *client)
*/ */
reg = (reg >> data->sar_shift) & data->sar_mask; reg = (reg >> data->sar_shift) & data->sar_mask;
return reg; *val = volts_from_reg(data, reg);
}
static inline u16 volts_from_reg(struct mcp3021_data *data, u16 val) return 0;
{
return DIV_ROUND_CLOSEST(data->vdd * val, 1 << data->output_res);
} }
static ssize_t in0_input_show(struct device *dev, static umode_t mcp3021_is_visible(const void *_data,
struct device_attribute *attr, char *buf) enum hwmon_sensor_types type,
u32 attr, int channel)
{ {
struct i2c_client *client = to_i2c_client(dev); if (type != hwmon_in)
struct mcp3021_data *data = i2c_get_clientdata(client); return 0;
int reg, in_input;
reg = mcp3021_read16(client); if (attr != hwmon_in_input)
if (reg < 0) return 0;
return reg;
in_input = volts_from_reg(data, reg); return 0444;
return sprintf(buf, "%d\n", in_input);
} }
static DEVICE_ATTR_RO(in0_input); static const struct hwmon_channel_info *mcp3021_info[] = {
HWMON_CHANNEL_INFO(in, HWMON_I_INPUT),
NULL
};
static const struct hwmon_ops mcp3021_hwmon_ops = {
.is_visible = mcp3021_is_visible,
.read = mcp3021_read,
};
static const struct hwmon_chip_info mcp3021_chip_info = {
.ops = &mcp3021_hwmon_ops,
.info = mcp3021_info,
};
static const struct i2c_device_id mcp3021_id[]; static const struct i2c_device_id mcp3021_id[];
static int mcp3021_probe(struct i2c_client *client) static int mcp3021_probe(struct i2c_client *client)
{ {
int err;
struct mcp3021_data *data = NULL; struct mcp3021_data *data = NULL;
struct device_node *np = client->dev.of_node; struct device_node *np = client->dev.of_node;
struct device *hwmon_dev;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV; return -ENODEV;
...@@ -147,34 +164,17 @@ static int mcp3021_probe(struct i2c_client *client) ...@@ -147,34 +164,17 @@ static int mcp3021_probe(struct i2c_client *client)
break; break;
} }
data->client = client;
if (data->vdd > MCP3021_VDD_REF_MAX || data->vdd < MCP3021_VDD_REF_MIN) if (data->vdd > MCP3021_VDD_REF_MAX || data->vdd < MCP3021_VDD_REF_MIN)
return -EINVAL; return -EINVAL;
err = sysfs_create_file(&client->dev.kobj, &dev_attr_in0_input.attr); hwmon_dev = devm_hwmon_device_register_with_info(&client->dev,
if (err) client->name,
return err; data,
&mcp3021_chip_info,
data->hwmon_dev = hwmon_device_register(&client->dev); NULL);
if (IS_ERR(data->hwmon_dev)) { return PTR_ERR_OR_ZERO(hwmon_dev);
err = PTR_ERR(data->hwmon_dev);
goto exit_remove;
}
return 0;
exit_remove:
sysfs_remove_file(&client->dev.kobj, &dev_attr_in0_input.attr);
return err;
}
static int mcp3021_remove(struct i2c_client *client)
{
struct mcp3021_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_file(&client->dev.kobj, &dev_attr_in0_input.attr);
return 0;
} }
static const struct i2c_device_id mcp3021_id[] = { static const struct i2c_device_id mcp3021_id[] = {
...@@ -199,7 +199,6 @@ static struct i2c_driver mcp3021_driver = { ...@@ -199,7 +199,6 @@ static struct i2c_driver mcp3021_driver = {
.of_match_table = of_match_ptr(of_mcp3021_match), .of_match_table = of_match_ptr(of_mcp3021_match),
}, },
.probe_new = mcp3021_probe, .probe_new = mcp3021_probe,
.remove = mcp3021_remove,
.id_table = mcp3021_id, .id_table = mcp3021_id,
}; };
......
...@@ -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
......
// SPDX-License-Identifier: GPL-2.0+
/*
* Hardware monitoring driver for Analog Devices LT7182S
*
* Copyright (c) 2022 Guenter Roeck
*
*/
#include <linux/bits.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include "pmbus.h"
#define LT7182S_NUM_PAGES 2
#define MFR_READ_EXTVCC 0xcd
#define MFR_READ_ITH 0xce
#define MFR_CONFIG_ALL_LT7182S 0xd1
#define MFR_IOUT_PEAK 0xd7
#define MFR_ADC_CONTROL_LT7182S 0xd8
#define MFR_DEBUG_TELEMETRY BIT(0)
#define MFR_VOUT_PEAK 0xdd
#define MFR_VIN_PEAK 0xde
#define MFR_TEMPERATURE_1_PEAK 0xdf
#define MFR_CLEAR_PEAKS 0xe3
#define MFR_CONFIG_IEEE BIT(8)
static int lt7182s_read_word_data(struct i2c_client *client, int page, int phase, int reg)
{
int ret;
switch (reg) {
case PMBUS_VIRT_READ_VMON:
if (page == 0 || page == 1)
ret = pmbus_read_word_data(client, page, phase, MFR_READ_ITH);
else
ret = pmbus_read_word_data(client, 0, phase, MFR_READ_EXTVCC);
break;
case PMBUS_VIRT_READ_IOUT_MAX:
ret = pmbus_read_word_data(client, page, phase, MFR_IOUT_PEAK);
break;
case PMBUS_VIRT_READ_VOUT_MAX:
ret = pmbus_read_word_data(client, page, phase, MFR_VOUT_PEAK);
break;
case PMBUS_VIRT_READ_VIN_MAX:
ret = pmbus_read_word_data(client, page, phase, MFR_VIN_PEAK);
break;
case PMBUS_VIRT_READ_TEMP_MAX:
ret = pmbus_read_word_data(client, page, phase, MFR_TEMPERATURE_1_PEAK);
break;
case PMBUS_VIRT_RESET_VIN_HISTORY:
ret = (page == 0) ? 0 : -ENODATA;
break;
default:
ret = -ENODATA;
break;
}
return ret;
}
static int lt7182s_write_word_data(struct i2c_client *client, int page, int reg, u16 word)
{
int ret;
switch (reg) {
case PMBUS_VIRT_RESET_VIN_HISTORY:
ret = pmbus_write_byte(client, 0, MFR_CLEAR_PEAKS);
break;
default:
ret = -ENODATA;
break;
}
return ret;
}
static struct pmbus_driver_info lt7182s_info = {
.pages = LT7182S_NUM_PAGES,
.format[PSC_VOLTAGE_IN] = linear,
.format[PSC_VOLTAGE_OUT] = linear,
.format[PSC_CURRENT_IN] = linear,
.format[PSC_CURRENT_OUT] = linear,
.format[PSC_TEMPERATURE] = linear,
.format[PSC_POWER] = linear,
.func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT |
PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_POUT |
PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT |
PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP,
.func[1] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT |
PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_POUT |
PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT |
PMBUS_HAVE_STATUS_INPUT,
.read_word_data = lt7182s_read_word_data,
.write_word_data = lt7182s_write_word_data,
};
static int lt7182s_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct pmbus_driver_info *info;
u8 buf[I2C_SMBUS_BLOCK_MAX + 1];
int ret;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_READ_BYTE_DATA |
I2C_FUNC_SMBUS_READ_WORD_DATA |
I2C_FUNC_SMBUS_READ_BLOCK_DATA))
return -ENODEV;
ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, buf);
if (ret < 0) {
dev_err(dev, "Failed to read PMBUS_MFR_ID\n");
return ret;
}
if (ret != 3 || strncmp(buf, "ADI", 3)) {
buf[ret] = '\0';
dev_err(dev, "Manufacturer '%s' not supported\n", buf);
return -ENODEV;
}
ret = i2c_smbus_read_block_data(client, PMBUS_MFR_MODEL, buf);
if (ret < 0) {
dev_err(dev, "Failed to read PMBUS_MFR_MODEL\n");
return ret;
}
if (ret != 7 || strncmp(buf, "LT7182S", 7)) {
buf[ret] = '\0';
dev_err(dev, "Model '%s' not supported\n", buf);
return -ENODEV;
}
info = devm_kmemdup(dev, &lt7182s_info,
sizeof(struct pmbus_driver_info), GFP_KERNEL);
if (!info)
return -ENOMEM;
/* Set data format to IEEE754 if configured */
ret = i2c_smbus_read_word_data(client, MFR_CONFIG_ALL_LT7182S);
if (ret < 0)
return ret;
if (ret & MFR_CONFIG_IEEE) {
info->format[PSC_VOLTAGE_IN] = ieee754;
info->format[PSC_VOLTAGE_OUT] = ieee754;
info->format[PSC_CURRENT_IN] = ieee754;
info->format[PSC_CURRENT_OUT] = ieee754;
info->format[PSC_TEMPERATURE] = ieee754;
info->format[PSC_POWER] = ieee754;
}
/* Enable VMON output if configured */
ret = i2c_smbus_read_byte_data(client, MFR_ADC_CONTROL_LT7182S);
if (ret < 0)
return ret;
if (ret & MFR_DEBUG_TELEMETRY) {
info->pages = 3;
info->func[0] |= PMBUS_HAVE_VMON;
info->func[1] |= PMBUS_HAVE_VMON;
info->func[2] = PMBUS_HAVE_VMON;
}
return pmbus_do_probe(client, info);
}
static const struct i2c_device_id lt7182s_id[] = {
{ "lt7182s", 0 },
{}
};
MODULE_DEVICE_TABLE(i2c, lt7182s_id);
static const struct of_device_id __maybe_unused lt7182s_of_match[] = {
{ .compatible = "adi,lt7182s" },
{}
};
static struct i2c_driver lt7182s_driver = {
.driver = {
.name = "lt7182s",
.of_match_table = of_match_ptr(lt7182s_of_match),
},
.probe_new = lt7182s_probe,
.id_table = lt7182s_id,
};
module_i2c_driver(lt7182s_driver);
MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
MODULE_DESCRIPTION("PMBus driver for Analog Devices LT7182S");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS(PMBUS);
...@@ -562,7 +562,24 @@ static const struct i2c_device_id ltc2978_id[] = { ...@@ -562,7 +562,24 @@ static const struct i2c_device_id ltc2978_id[] = {
MODULE_DEVICE_TABLE(i2c, ltc2978_id); MODULE_DEVICE_TABLE(i2c, ltc2978_id);
#if IS_ENABLED(CONFIG_SENSORS_LTC2978_REGULATOR) #if IS_ENABLED(CONFIG_SENSORS_LTC2978_REGULATOR)
#define LTC2978_ADC_RES 0xFFFF
#define LTC2978_N_ADC 122
#define LTC2978_MAX_UV (LTC2978_ADC_RES * LTC2978_N_ADC)
#define LTC2978_UV_STEP 1000
#define LTC2978_N_VOLTAGES ((LTC2978_MAX_UV / LTC2978_UV_STEP) + 1)
static const struct regulator_desc ltc2978_reg_desc[] = { static const struct regulator_desc ltc2978_reg_desc[] = {
PMBUS_REGULATOR_STEP("vout", 0, LTC2978_N_VOLTAGES, LTC2978_UV_STEP),
PMBUS_REGULATOR_STEP("vout", 1, LTC2978_N_VOLTAGES, LTC2978_UV_STEP),
PMBUS_REGULATOR_STEP("vout", 2, LTC2978_N_VOLTAGES, LTC2978_UV_STEP),
PMBUS_REGULATOR_STEP("vout", 3, LTC2978_N_VOLTAGES, LTC2978_UV_STEP),
PMBUS_REGULATOR_STEP("vout", 4, LTC2978_N_VOLTAGES, LTC2978_UV_STEP),
PMBUS_REGULATOR_STEP("vout", 5, LTC2978_N_VOLTAGES, LTC2978_UV_STEP),
PMBUS_REGULATOR_STEP("vout", 6, LTC2978_N_VOLTAGES, LTC2978_UV_STEP),
PMBUS_REGULATOR_STEP("vout", 7, LTC2978_N_VOLTAGES, LTC2978_UV_STEP),
};
static const struct regulator_desc ltc2978_reg_desc_default[] = {
PMBUS_REGULATOR("vout", 0), PMBUS_REGULATOR("vout", 0),
PMBUS_REGULATOR("vout", 1), PMBUS_REGULATOR("vout", 1),
PMBUS_REGULATOR("vout", 2), PMBUS_REGULATOR("vout", 2),
...@@ -839,10 +856,29 @@ static int ltc2978_probe(struct i2c_client *client) ...@@ -839,10 +856,29 @@ static int ltc2978_probe(struct i2c_client *client)
#if IS_ENABLED(CONFIG_SENSORS_LTC2978_REGULATOR) #if IS_ENABLED(CONFIG_SENSORS_LTC2978_REGULATOR)
info->num_regulators = info->pages; info->num_regulators = info->pages;
info->reg_desc = ltc2978_reg_desc; switch (data->id) {
if (info->num_regulators > ARRAY_SIZE(ltc2978_reg_desc)) { case ltc2972:
dev_err(&client->dev, "num_regulators too large!"); case ltc2974:
info->num_regulators = ARRAY_SIZE(ltc2978_reg_desc); case ltc2975:
case ltc2977:
case ltc2978:
case ltc2979:
case ltc2980:
case ltm2987:
info->reg_desc = ltc2978_reg_desc;
if (info->num_regulators > ARRAY_SIZE(ltc2978_reg_desc)) {
dev_warn(&client->dev, "num_regulators too large!");
info->num_regulators = ARRAY_SIZE(ltc2978_reg_desc);
}
break;
default:
info->reg_desc = ltc2978_reg_desc_default;
if (info->num_regulators > ARRAY_SIZE(ltc2978_reg_desc_default)) {
dev_warn(&client->dev, "num_regulators too large!");
info->num_regulators =
ARRAY_SIZE(ltc2978_reg_desc_default);
}
break;
} }
#endif #endif
......
...@@ -406,7 +406,7 @@ enum pmbus_sensor_classes { ...@@ -406,7 +406,7 @@ enum pmbus_sensor_classes {
#define PMBUS_PHASE_VIRTUAL BIT(30) /* Phases on this page are virtual */ #define PMBUS_PHASE_VIRTUAL BIT(30) /* Phases on this page are virtual */
#define PMBUS_PAGE_VIRTUAL BIT(31) /* Page is virtual */ #define PMBUS_PAGE_VIRTUAL BIT(31) /* Page is virtual */
enum pmbus_data_format { linear = 0, direct, vid }; enum pmbus_data_format { linear = 0, ieee754, direct, vid };
enum vrm_version { vr11 = 0, vr12, vr13, imvp9, amd625mv }; enum vrm_version { vr11 = 0, vr12, vr13, imvp9, amd625mv };
struct pmbus_driver_info { struct pmbus_driver_info {
...@@ -463,8 +463,8 @@ struct pmbus_driver_info { ...@@ -463,8 +463,8 @@ struct pmbus_driver_info {
extern const struct regulator_ops pmbus_regulator_ops; extern const struct regulator_ops pmbus_regulator_ops;
/* Macro for filling in array of struct regulator_desc */ /* Macros for filling in array of struct regulator_desc */
#define PMBUS_REGULATOR(_name, _id) \ #define PMBUS_REGULATOR_STEP(_name, _id, _voltages, _step) \
[_id] = { \ [_id] = { \
.name = (_name # _id), \ .name = (_name # _id), \
.supply_name = "vin", \ .supply_name = "vin", \
...@@ -474,8 +474,12 @@ extern const struct regulator_ops pmbus_regulator_ops; ...@@ -474,8 +474,12 @@ extern const struct regulator_ops pmbus_regulator_ops;
.ops = &pmbus_regulator_ops, \ .ops = &pmbus_regulator_ops, \
.type = REGULATOR_VOLTAGE, \ .type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \ .owner = THIS_MODULE, \
.n_voltages = _voltages, \
.uV_step = _step, \
} }
#define PMBUS_REGULATOR(_name, _id) PMBUS_REGULATOR_STEP(_name, _id, 0, 0)
/* Function declarations */ /* Function declarations */
void pmbus_clear_cache(struct i2c_client *client); void pmbus_clear_cache(struct i2c_client *client);
......
This diff is collapsed.
...@@ -523,6 +523,28 @@ static int __init sch56xx_device_add(int address, const char *name) ...@@ -523,6 +523,28 @@ static int __init sch56xx_device_add(int address, const char *name)
return PTR_ERR_OR_ZERO(sch56xx_pdev); return PTR_ERR_OR_ZERO(sch56xx_pdev);
} }
static const struct dmi_system_id sch56xx_dmi_override_table[] __initconst = {
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS W380"),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO P710"),
},
},
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO E9900"),
},
},
{ }
};
/* For autoloading only */ /* For autoloading only */
static const struct dmi_system_id sch56xx_dmi_table[] __initconst = { static const struct dmi_system_id sch56xx_dmi_table[] __initconst = {
{ {
...@@ -543,16 +565,18 @@ static int __init sch56xx_init(void) ...@@ -543,16 +565,18 @@ static int __init sch56xx_init(void)
if (!dmi_check_system(sch56xx_dmi_table)) if (!dmi_check_system(sch56xx_dmi_table))
return -ENODEV; return -ENODEV;
/* if (!dmi_check_system(sch56xx_dmi_override_table)) {
* Some machines like the Esprimo P720 and Esprimo C700 have /*
* onboard devices named " Antiope"/" Theseus" instead of * Some machines like the Esprimo P720 and Esprimo C700 have
* "Antiope"/"Theseus", so we need to check for both. * onboard devices named " Antiope"/" Theseus" instead of
*/ * "Antiope"/"Theseus", so we need to check for both.
if (!dmi_find_device(DMI_DEV_TYPE_OTHER, "Antiope", NULL) && */
!dmi_find_device(DMI_DEV_TYPE_OTHER, " Antiope", NULL) && if (!dmi_find_device(DMI_DEV_TYPE_OTHER, "Antiope", NULL) &&
!dmi_find_device(DMI_DEV_TYPE_OTHER, "Theseus", NULL) && !dmi_find_device(DMI_DEV_TYPE_OTHER, " Antiope", NULL) &&
!dmi_find_device(DMI_DEV_TYPE_OTHER, " Theseus", NULL)) !dmi_find_device(DMI_DEV_TYPE_OTHER, "Theseus", NULL) &&
return -ENODEV; !dmi_find_device(DMI_DEV_TYPE_OTHER, " Theseus", NULL))
return -ENODEV;
}
} }
/* /*
......
...@@ -1020,25 +1020,20 @@ static int sht15_probe(struct platform_device *pdev) ...@@ -1020,25 +1020,20 @@ static int sht15_probe(struct platform_device *pdev)
static int sht15_remove(struct platform_device *pdev) static int sht15_remove(struct platform_device *pdev)
{ {
struct sht15_data *data = platform_get_drvdata(pdev); struct sht15_data *data = platform_get_drvdata(pdev);
int ret;
/*
* Make sure any reads from the device are done and
* prevent new ones beginning
*/
mutex_lock(&data->read_lock);
if (sht15_soft_reset(data)) {
mutex_unlock(&data->read_lock);
return -EFAULT;
}
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&pdev->dev.kobj, &sht15_attr_group); sysfs_remove_group(&pdev->dev.kobj, &sht15_attr_group);
ret = sht15_soft_reset(data);
if (ret)
dev_err(&pdev->dev, "Failed to reset device (%pe)\n", ERR_PTR(ret));
if (!IS_ERR(data->reg)) { if (!IS_ERR(data->reg)) {
regulator_unregister_notifier(data->reg, &data->nb); regulator_unregister_notifier(data->reg, &data->nb);
regulator_disable(data->reg); regulator_disable(data->reg);
} }
mutex_unlock(&data->read_lock);
return 0; return 0;
} }
......
...@@ -140,7 +140,8 @@ static int tps23861_read_temp(struct tps23861_data *data, long *val) ...@@ -140,7 +140,8 @@ static int tps23861_read_temp(struct tps23861_data *data, long *val)
static int tps23861_read_voltage(struct tps23861_data *data, int channel, static int tps23861_read_voltage(struct tps23861_data *data, int channel,
long *val) long *val)
{ {
unsigned int regval; __le16 regval;
long raw_val;
int err; int err;
if (channel < TPS23861_NUM_PORTS) { if (channel < TPS23861_NUM_PORTS) {
...@@ -155,7 +156,8 @@ static int tps23861_read_voltage(struct tps23861_data *data, int channel, ...@@ -155,7 +156,8 @@ static int tps23861_read_voltage(struct tps23861_data *data, int channel,
if (err < 0) if (err < 0)
return err; return err;
*val = (FIELD_GET(VOLTAGE_CURRENT_MASK, regval) * VOLTAGE_LSB) / 1000; raw_val = le16_to_cpu(regval);
*val = (FIELD_GET(VOLTAGE_CURRENT_MASK, raw_val) * VOLTAGE_LSB) / 1000;
return 0; return 0;
} }
...@@ -163,8 +165,9 @@ static int tps23861_read_voltage(struct tps23861_data *data, int channel, ...@@ -163,8 +165,9 @@ static int tps23861_read_voltage(struct tps23861_data *data, int channel,
static int tps23861_read_current(struct tps23861_data *data, int channel, static int tps23861_read_current(struct tps23861_data *data, int channel,
long *val) long *val)
{ {
unsigned int current_lsb; long raw_val, current_lsb;
unsigned int regval; __le16 regval;
int err; int err;
if (data->shunt_resistor == SHUNT_RESISTOR_DEFAULT) if (data->shunt_resistor == SHUNT_RESISTOR_DEFAULT)
...@@ -178,7 +181,8 @@ static int tps23861_read_current(struct tps23861_data *data, int channel, ...@@ -178,7 +181,8 @@ static int tps23861_read_current(struct tps23861_data *data, int channel,
if (err < 0) if (err < 0)
return err; return err;
*val = (FIELD_GET(VOLTAGE_CURRENT_MASK, regval) * current_lsb) / 1000000; raw_val = le16_to_cpu(regval);
*val = (FIELD_GET(VOLTAGE_CURRENT_MASK, raw_val) * current_lsb) / 1000000;
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment