Commit c27ea952 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull hwmon updates from Guenter Roeck:
 "New drivers:
   - driver for Sophgo SG2042 external hardware monitor
   - thermal sensor driver for Surface Aggregator Module

  Added support to existing drivers:
   - oxp-sensors: Support for multiple new devices.
   - nct6775: Added G15CF to ASUS WMI monitoring list

  Modernizations:
   - driver cleanup and update to use with_info API: ina2xx, lm92,
     lm95234, max1619, max1668, and max6697.

  API updates:
   - removed unused devm_hwmon_device_unregister() API function

  Other notable changes
   - implement and use generic bus access delay for pmbus drivers
   - use with scoped for each OF child loop in several drivers
   - module unloading fixes for gsc-hwmon and ntc_thermistor drivers
   - converted various drivers to use multi-byte regmap operations
   - adt7475: Improved devicetree based configuration
   - ltc2947: Move to firmware agnostic API
   - ltc2978: Converted devicetree description to yaml
   - max16065: Addressed overflows when writing limit attributes

  Various other minor cleanups, fixes and improvements"

* tag 'hwmon-for-v6.12' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (96 commits)
  hwmon: Remove devm_hwmon_device_unregister() API function
  hwmon: (sch5636) Print unknown ID in error string via %*pE
  hwmon: (sht21) Use %*ph to print small buffer
  hwmon: (pmbus/mpq7932) Constify struct regulator_desc
  hwmon: pmbus: pli12096bc: Add write delay
  hwmon: pmbus: zl6100: Use generic code
  hwmon: pmbus: ucd9000: Use generic code
  hwmon: pmbus: max15301: Use generic code
  hwmon: pmbus: Implement generic bus access delay
  hwmon: (ina2xx) Use shunt voltage to calculate current
  hwmon: (ina2xx) Add support for current limits
  hwmon: (ina2xx) Pass register to alert limit write functions
  hwmon: (ina2xx) Convert to use with_info hwmon API
  hwmon: (ina2xx) Move ina2xx_get_value()
  hwmon: (ina2xx) Set alert latch
  hwmon: (ina2xx) Consolidate chip initialization code
  hwmon: (ina2xx) Fix various overflow issues
  hwmon: (ina2xx) Re-initialize chip using regmap functions
  hwmon: (ina2xx) Use local regmap pointer if used more than once
  hwmon: (ina2xx) Mark regmap_config as const
  ...
parents 39b3f4e0 2cb4acf2
...@@ -45,12 +45,31 @@ properties: ...@@ -45,12 +45,31 @@ properties:
the pwm uses a logic low output for 100% duty cycle. If set to 1 the pwm the pwm uses a logic low output for 100% duty cycle. If set to 1 the pwm
uses a logic high output for 100% duty cycle. uses a logic high output for 100% duty cycle.
$ref: /schemas/types.yaml#/definitions/uint32-array $ref: /schemas/types.yaml#/definitions/uint32-array
deprecated: true
minItems: 3 minItems: 3
maxItems: 3 maxItems: 3
items: items:
enum: [0, 1] enum: [0, 1]
default: 1 default: 1
"#pwm-cells":
const: 4
description: |
Number of cells in a PWM specifier.
- 0: The PWM channel
- 1: The PWM period in nanoseconds
- 90909091 (11 Hz)
- 71428571 (14 Hz)
- 45454545 (22 Hz)
- 34482759 (29 Hz)
- 28571429 (35 Hz)
- 22727273 (44 Hz)
- 17241379 (58 Hz)
- 11363636 (88 Hz)
- 44444 (22 kHz)
- 2: PWM flags 0 or PWM_POLARITY_INVERTED
- 3: The default PWM duty cycle in nanoseconds
patternProperties: patternProperties:
"^adi,bypass-attenuator-in[0-4]$": "^adi,bypass-attenuator-in[0-4]$":
description: | description: |
...@@ -81,6 +100,10 @@ patternProperties: ...@@ -81,6 +100,10 @@ patternProperties:
- smbalert# - smbalert#
- gpio - gpio
"^fan-[0-9]+$":
$ref: fan-common.yaml#
unevaluatedProperties: false
required: required:
- compatible - compatible
- reg - reg
...@@ -89,17 +112,27 @@ additionalProperties: false ...@@ -89,17 +112,27 @@ additionalProperties: false
examples: examples:
- | - |
#include <dt-bindings/pwm/pwm.h>
i2c { i2c {
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
hwmon@2e { pwm: hwmon@2e {
compatible = "adi,adt7476"; compatible = "adi,adt7476";
reg = <0x2e>; reg = <0x2e>;
adi,bypass-attenuator-in0 = <1>; adi,bypass-attenuator-in0 = <1>;
adi,bypass-attenuator-in1 = <0>; adi,bypass-attenuator-in1 = <0>;
adi,pwm-active-state = <1 0 1>;
adi,pin10-function = "smbalert#"; adi,pin10-function = "smbalert#";
adi,pin14-function = "tach4"; adi,pin14-function = "tach4";
#pwm-cells = <4>;
/* PWMs at 22.5 kHz frequency, 50% duty*/
fan-0 {
pwms = <&pwm 0 44444 0 22222>;
};
fan-1 {
pwms = <&pwm 2 44444 0 22222>;
};
}; };
}; };
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/hwmon/lltc,ltc2978.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Octal Digital Power-supply monitor/supervisor/sequencer/margin controller.
maintainers:
- Frank Li <Frank.Li@nxp.com>
properties:
compatible:
enum:
- lltc,ltc2972
- lltc,ltc2974
- lltc,ltc2975
- lltc,ltc2977
- lltc,ltc2978
- lltc,ltc2979
- lltc,ltc2980
- lltc,ltc3880
- lltc,ltc3882
- lltc,ltc3883
- lltc,ltc3884
- lltc,ltc3886
- lltc,ltc3887
- lltc,ltc3889
- lltc,ltc7880
- lltc,ltm2987
- lltc,ltm4664
- lltc,ltm4675
- lltc,ltm4676
- lltc,ltm4677
- lltc,ltm4678
- lltc,ltm4680
- lltc,ltm4686
- lltc,ltm4700
reg:
maxItems: 1
regulators:
type: object
description: |
list of regulators provided by this controller.
Valid names of regulators depend on number of supplies supported per device:
* ltc2972 vout0 - vout1
* ltc2974, ltc2975 : vout0 - vout3
* ltc2977, ltc2979, ltc2980, ltm2987 : vout0 - vout7
* ltc2978 : vout0 - vout7
* ltc3880, ltc3882, ltc3884, ltc3886, ltc3887, ltc3889 : vout0 - vout1
* ltc7880 : vout0 - vout1
* ltc3883 : vout0
* ltm4664 : vout0 - vout1
* ltm4675, ltm4676, ltm4677, ltm4678 : vout0 - vout1
* ltm4680, ltm4686 : vout0 - vout1
* ltm4700 : vout0 - vout1
patternProperties:
"^vout[0-7]$":
$ref: /schemas/regulator/regulator.yaml#
type: object
unevaluatedProperties: false
additionalProperties: false
required:
- compatible
- reg
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
regulator@5e {
compatible = "lltc,ltc2978";
reg = <0x5e>;
regulators {
vout0 {
regulator-name = "FPGA-2.5V";
};
vout2 {
regulator-name = "FPGA-1.5V";
};
};
};
};
ltc2978
Required properties:
- compatible: should contain one of:
* "lltc,ltc2972"
* "lltc,ltc2974"
* "lltc,ltc2975"
* "lltc,ltc2977"
* "lltc,ltc2978"
* "lltc,ltc2979"
* "lltc,ltc2980"
* "lltc,ltc3880"
* "lltc,ltc3882"
* "lltc,ltc3883"
* "lltc,ltc3884"
* "lltc,ltc3886"
* "lltc,ltc3887"
* "lltc,ltc3889"
* "lltc,ltc7880"
* "lltc,ltm2987"
* "lltc,ltm4664"
* "lltc,ltm4675"
* "lltc,ltm4676"
* "lltc,ltm4677"
* "lltc,ltm4678"
* "lltc,ltm4680"
* "lltc,ltm4686"
* "lltc,ltm4700"
- reg: I2C slave address
Optional properties:
- regulators: A node that houses a sub-node for each regulator controlled by
the device. Each sub-node is identified using the node's name, with valid
values listed below. The content of each sub-node is defined by the
standard binding for regulators; see regulator.txt.
Valid names of regulators depend on number of supplies supported per device:
* ltc2972 vout0 - vout1
* ltc2974, ltc2975 : vout0 - vout3
* ltc2977, ltc2979, ltc2980, ltm2987 : vout0 - vout7
* ltc2978 : vout0 - vout7
* ltc3880, ltc3882, ltc3884, ltc3886, ltc3887, ltc3889 : vout0 - vout1
* ltc7880 : vout0 - vout1
* ltc3883 : vout0
* ltm4664 : vout0 - vout1
* ltm4675, ltm4676, ltm4677, ltm4678 : vout0 - vout1
* ltm4680, ltm4686 : vout0 - vout1
* ltm4700 : vout0 - vout1
Example:
ltc2978@5e {
compatible = "lltc,ltc2978";
reg = <0x5e>;
regulators {
vout0 {
regulator-name = "FPGA-2.5V";
};
vout2 {
regulator-name = "FPGA-1.5V";
};
};
};
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/hwmon/maxim,max31790.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: The Maxim MAX31790 Fan Controller
maintainers:
- Guenter Roeck <linux@roeck-us.net>
- Chanh Nguyen <chanh@os.amperecomputing.com>
description: >
The MAX31790 controls the speeds of up to six fans using six
independent PWM outputs. The desired fan speeds (or PWM duty cycles)
are written through the I2C interface.
Datasheets:
https://datasheets.maximintegrated.com/en/ds/MAX31790.pdf
properties:
compatible:
const: maxim,max31790
reg:
maxItems: 1
clocks:
maxItems: 1
resets:
maxItems: 1
"#pwm-cells":
const: 1
patternProperties:
"^fan-[0-9]+$":
$ref: fan-common.yaml#
unevaluatedProperties: false
required:
- compatible
- reg
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
pwm_provider: fan-controller@20 {
compatible = "maxim,max31790";
reg = <0x20>;
clocks = <&sys_clk>;
resets = <&reset 0>;
#pwm-cells = <1>;
fan-0 {
pwms = <&pwm_provider 1>;
};
fan-1 {
pwms = <&pwm_provider 2>;
};
};
};
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/hwmon/sophgo,sg2042-hwmon-mcu.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Sophgo SG2042 onboard MCU support
maintainers:
- Inochi Amaoto <inochiama@outlook.com>
properties:
compatible:
const: sophgo,sg2042-hwmon-mcu
reg:
maxItems: 1
"#thermal-sensor-cells":
const: 1
required:
- compatible
- reg
- "#thermal-sensor-cells"
allOf:
- $ref: /schemas/thermal/thermal-sensor.yaml#
unevaluatedProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
hwmon@17 {
compatible = "sophgo,sg2042-hwmon-mcu";
reg = <0x17>;
#thermal-sensor-cells = <1>;
};
};
...@@ -38,8 +38,6 @@ register/unregister functions:: ...@@ -38,8 +38,6 @@ register/unregister functions::
void hwmon_device_unregister(struct device *dev); void hwmon_device_unregister(struct device *dev);
void devm_hwmon_device_unregister(struct device *dev);
char *hwmon_sanitize_name(const char *name); char *hwmon_sanitize_name(const char *name);
char *devm_hwmon_sanitize_name(struct device *dev, const char *name); char *devm_hwmon_sanitize_name(struct device *dev, const char *name);
...@@ -64,11 +62,6 @@ monitoring device structure. This function must be called from the driver ...@@ -64,11 +62,6 @@ monitoring device structure. This function must be called from the driver
remove function if the hardware monitoring device was registered with remove function if the hardware monitoring device was registered with
hwmon_device_register_with_info. hwmon_device_register_with_info.
devm_hwmon_device_unregister does not normally have to be called. It is only
needed for error handling, and only needed if the driver probe fails after
the call to devm_hwmon_device_register_with_info and if the automatic (device
managed) removal would be too late.
All supported hwmon device registration functions only accept valid device All supported hwmon device registration functions only accept valid device
names. Device names including invalid characters (whitespace, '*', or '-') names. Device names including invalid characters (whitespace, '*', or '-')
will be rejected. The 'name' parameter is mandatory. will be rejected. The 'name' parameter is mandatory.
......
...@@ -99,6 +99,10 @@ Sysfs entries for ina226, ina230 and ina231 only ...@@ -99,6 +99,10 @@ Sysfs entries for ina226, ina230 and ina231 only
------------------------------------------------ ------------------------------------------------
======================= ==================================================== ======================= ====================================================
curr1_lcrit Critical low current
curr1_crit Critical high current
curr1_lcrit_alarm Current critical low alarm
curr1_crit_alarm Current critical high alarm
in0_lcrit Critical low shunt voltage in0_lcrit Critical low shunt voltage
in0_crit Critical high shunt voltage in0_crit Critical high shunt voltage
in0_lcrit_alarm Shunt voltage critical low alarm in0_lcrit_alarm Shunt voltage critical low alarm
......
...@@ -206,6 +206,7 @@ Hardware Monitoring Kernel Drivers ...@@ -206,6 +206,7 @@ Hardware Monitoring Kernel Drivers
sch5636 sch5636
scpi-hwmon scpi-hwmon
sfctemp sfctemp
sg2042-mcu
sht15 sht15
sht21 sht21
sht3x sht3x
......
...@@ -3,29 +3,29 @@ Kernel driver lm92 ...@@ -3,29 +3,29 @@ Kernel driver lm92
Supported chips: Supported chips:
* National Semiconductor LM92 * National Semiconductor / Texas Instruments LM92
Prefix: 'lm92' Prefix: 'lm92'
Addresses scanned: I2C 0x48 - 0x4b Addresses scanned: I2C 0x48 - 0x4b
Datasheet: http://www.national.com/pf/LM/LM92.html Datasheet: https://www.ti.com/lit/gpn/LM92
* National Semiconductor LM76 * National Semiconductor / Texas Instruments LM76
Prefix: 'lm92' Prefix: 'lm92'
Addresses scanned: none, force parameter needed Addresses scanned: none, must be instantiated explicitly
Datasheet: http://www.national.com/pf/LM/LM76.html Datasheet: https://www.ti.com/lit/gpn/LM76
* Maxim MAX6633/MAX6634/MAX6635 * Maxim /Analog Devices MAX6633/MAX6634/MAX6635
Prefix: 'max6635' Prefix: 'max6635'
Addresses scanned: none, force parameter needed Addresses scanned: none, must be instantiated explicitly
Datasheet: http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3074 Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/max6633-max6635.pdf
Authors: Authors:
...@@ -36,13 +36,13 @@ Authors: ...@@ -36,13 +36,13 @@ Authors:
Description Description
----------- -----------
This driver implements support for the National Semiconductor LM92 This driver implements support for the National Semiconductor / Texas
temperature sensor. Instruments LM92 temperature sensor.
Each LM92 temperature sensor supports a single temperature sensor. There are Each LM92 temperature sensor supports a single temperature sensor. There are
alarms for high, low, and critical thresholds. There's also an hysteresis to alarms for high, low, and critical thresholds. There's also an hysteresis to
control the thresholds for resetting alarms. control the thresholds for resetting alarms.
Support was added later for the LM76 and Maxim MAX6633/MAX6634/MAX6635, The driver also supports LM76 and Maxim MAX6633/MAX6634/MAX6635, which are
which are mostly compatible. They have not all been tested, so you mostly compatible but do not have a vendor ID register and therefore must be
may need to use the force parameter. instantiated explicitly.
...@@ -27,7 +27,3 @@ All temperature values are given in degrees Celsius. Resolution ...@@ -27,7 +27,3 @@ All temperature values are given in degrees Celsius. Resolution
is 1.0 degree for the local temperature and for the remote temperature. is 1.0 degree for the local temperature and for the remote temperature.
Only the external sensor has high and low limits. Only the external sensor has high and low limits.
The max1619 driver will not update its values more frequently than every
other second; reading them more often will do no harm, but will return
'old' values.
...@@ -10,41 +10,59 @@ Authors: ...@@ -10,41 +10,59 @@ Authors:
Description: Description:
------------ ------------
Handheld devices from One Netbook and Aya Neo provide fan readings and fan Handheld devices from OneNetbook, AOKZOE, AYANEO, And OrangePi provide fan
control through their embedded controllers. readings and fan control through their embedded controllers.
Currently only supports AMD boards from One X Player, AOK ZOE, and some Aya Currently supports OneXPlayer devices, AOKZOE, AYANEO, and OrangePi
Neo devices. One X Player Intel boards could be supported if we could figure handheld devices. AYANEO devices preceding the AIR and OneXPlayer devices
out the EC registers and values to write to since the EC layout and model is preceding the Mini A07 are not supportable as the EC model is different
different. Aya Neo devices preceding the AIR may not be supportable as the EC and do not have manual control capabilities.
model is different and do not appear to have manual control capabilities.
Some models have a toggle for changing the behaviour of the "Turbo/Silent" Some OneXPlayer and AOKZOE models have a toggle for changing the behaviour
button of the device. It will change the key event that it triggers with of the "Turbo/Silent" button of the device. It will change the key event
a flip of the `tt_toggle` attribute. See below for boards that support this that it triggers with a flip of the `tt_toggle` attribute. See below for
function. boards that support this function.
Supported devices Supported devices
----------------- -----------------
Currently the driver supports the following handhelds: Currently the driver supports the following handhelds:
- AOK ZOE A1 - AOKZOE A1
- AOK ZOE A1 PRO - AOKZOE A1 PRO
- Aya Neo 2 - AYANEO 2
- Aya Neo AIR - AYANEO 2S
- Aya Neo AIR Plus (Mendocino) - AYANEO AIR
- Aya Neo AIR Pro - AYANEO AIR 1S
- Aya Neo Geek - AYANEO AIR Plus (Mendocino)
- AYANEO AIR Pro
- AYANEO Flip DS
- AYANEO Flip KB
- AYANEO Geek
- AYANEO Geek 1S
- AYANEO KUN
- OneXPlayer 2
- OneXPlayer 2 Pro
- OneXPlayer AMD - OneXPlayer AMD
- OneXPlayer mini AMD - OneXPlayer mini AMD
- OneXPlayer mini AMD PRO - OneXPlayer mini AMD PRO
- OneXPlayer OneXFly
- OneXPlayer X1 A
- OneXPlayer X1 i
- OneXPlayer X1 mini
- OrangePi NEO-01
"Turbo/Silent" button behaviour toggle is only supported on: "Turbo/Silent" button behaviour toggle is only supported on:
- AOK ZOE A1 - AOK ZOE A1
- AOK ZOE A1 PRO - AOK ZOE A1 PRO
- OneXPlayer 2
- OneXPlayer 2 Pro
- OneXPlayer mini AMD (only with updated alpha BIOS) - OneXPlayer mini AMD (only with updated alpha BIOS)
- OneXPlayer mini AMD PRO - OneXPlayer mini AMD PRO
- OneXPlayer OneXFly
- OneXPlayer X1 A
- OneXPlayer X1 i
- OneXPlayer X1 mini
Sysfs entries Sysfs entries
------------- -------------
...@@ -52,7 +70,7 @@ Sysfs entries ...@@ -52,7 +70,7 @@ Sysfs entries
The following attributes are supported: The following attributes are supported:
fan1_input fan1_input
Read Only. Reads current fan RMP. Read Only. Reads current fan RPM.
pwm1_enable pwm1_enable
Read Write. Enable manual fan control. Write "1" to set to manual, write "0" Read Write. Enable manual fan control. Write "1" to set to manual, write "0"
......
.. SPDX-License-Identifier: GPL-2.0
Kernel driver sg2042-mcu
========================
Supported chips:
* Onboard MCU for sg2042
Addresses scanned: -
Prefix: 'sg2042-mcu'
Authors:
- Inochi Amaoto <inochiama@outlook.com>
Description
-----------
This driver supprts hardware monitoring for onboard MCU with
i2c interface.
Usage Notes
-----------
This driver does not auto-detect devices. You will have to instantiate
the devices explicitly.
Please see Documentation/i2c/instantiating-devices.rst for details.
Sysfs Attributes
----------------
The following table shows the standard entries support by the driver:
================= =====================================================
Name Description
================= =====================================================
temp1_input Measured temperature of SoC
temp1_crit Critical high temperature
temp1_crit_hyst hysteresis temperature restore from Critical
temp2_input Measured temperature of the base board
================= =====================================================
The following table shows the extra entries support by the driver
(the MCU device is in i2c subsystem):
================= ======= =============================================
Name Perm Description
================= ======= =============================================
reset_count RO Reset count of the SoC
uptime RO Seconds after the MCU is powered
reset_reason RO Reset reason for the last reset
repower_policy RW Execution policy when triggering repower
================= ======= =============================================
``repower_policy``
The repower is triggered when the temperature of the SoC falls below
the hysteresis temperature after triggering a shutdown due to
reaching the critical temperature.
The valid values for this entry are "repower" and "keep". "keep" will
leave the SoC down when the triggering repower, and "repower" will
boot the SoC.
Debugfs Interfaces
------------------
If debugfs is available, this driver exposes some hardware specific
data in ``/sys/kernel/debug/sg2042-mcu/*/``.
================= ======= =============================================
Name Format Description
================= ======= =============================================
firmware_version 0x%02x firmware version of the MCU
pcb_version 0x%02x version number of the base board
board_type 0x%02x identifiers for the base board
mcu_type %d type of the MCU: 0 is STM32, 1 is GD32
================= ======= =============================================
...@@ -15295,6 +15295,12 @@ S: Maintained ...@@ -15295,6 +15295,12 @@ S: Maintained
F: Documentation/hwmon/surface_fan.rst F: Documentation/hwmon/surface_fan.rst
F: drivers/hwmon/surface_fan.c F: drivers/hwmon/surface_fan.c
MICROSOFT SURFACE SENSOR THERMAL DRIVER
M: Maximilian Luz <luzmaximilian@gmail.com>
L: linux-hwmon@vger.kernel.org
S: Maintained
F: drivers/hwmon/surface_temp.c
MICROSOFT SURFACE GPE LID SUPPORT DRIVER MICROSOFT SURFACE GPE LID SUPPORT DRIVER
M: Maximilian Luz <luzmaximilian@gmail.com> M: Maximilian Luz <luzmaximilian@gmail.com>
L: platform-driver-x86@vger.kernel.org L: platform-driver-x86@vger.kernel.org
......
...@@ -1511,9 +1511,10 @@ config SENSORS_LM90 ...@@ -1511,9 +1511,10 @@ config SENSORS_LM90
config SENSORS_LM92 config SENSORS_LM92
tristate "National Semiconductor LM92 and compatibles" tristate "National Semiconductor LM92 and compatibles"
depends on I2C depends on I2C
select REGMAP_I2C
help help
If you say yes here you get support for National Semiconductor LM92 If you say yes here you get support for National Semiconductor LM92
and Maxim MAX6635 sensor chips. and LM76 as well as Maxim MAX6633/6634/6635 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
will be called lm92. will be called lm92.
...@@ -1532,6 +1533,7 @@ config SENSORS_LM93 ...@@ -1532,6 +1533,7 @@ config SENSORS_LM93
config SENSORS_LM95234 config SENSORS_LM95234
tristate "National Semiconductor LM95234 and compatibles" tristate "National Semiconductor LM95234 and compatibles"
depends on I2C depends on I2C
select REGMAP_I2C
help help
If you say yes here you get support for the LM95233 and LM95234 If you say yes here you get support for the LM95233 and LM95234
temperature sensor chips. temperature sensor chips.
...@@ -2066,6 +2068,17 @@ config SENSORS_SFCTEMP ...@@ -2066,6 +2068,17 @@ config SENSORS_SFCTEMP
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
will be called sfctemp. will be called sfctemp.
config SENSORS_SG2042_MCU
tristate "Sophgo onboard MCU support"
depends on I2C
depends on ARCH_SOPHGO || COMPILE_TEST
help
Support for onboard MCU of Sophgo SG2042 SoCs. This mcu provides
power control and some basic information.
This driver can be built as a module. If so, the module
will be called sg2042-mcu.
config SENSORS_SURFACE_FAN config SENSORS_SURFACE_FAN
tristate "Surface Fan Driver" tristate "Surface Fan Driver"
depends on SURFACE_AGGREGATOR depends on SURFACE_AGGREGATOR
...@@ -2080,6 +2093,17 @@ config SENSORS_SURFACE_FAN ...@@ -2080,6 +2093,17 @@ config SENSORS_SURFACE_FAN
Select M or Y here, if you want to be able to read the fan's speed. Select M or Y here, if you want to be able to read the fan's speed.
config SENSORS_SURFACE_TEMP
tristate "Microsoft Surface Thermal Sensor Driver"
depends on SURFACE_AGGREGATOR
depends on SURFACE_AGGREGATOR_BUS
help
Driver for monitoring thermal sensors connected via the Surface
Aggregator Module (embedded controller) on Microsoft Surface devices.
This driver can also be built as a module. If so, the module
will be called surface_temp.
config SENSORS_ADC128D818 config SENSORS_ADC128D818
tristate "Texas Instruments ADC128D818" tristate "Texas Instruments ADC128D818"
depends on I2C depends on I2C
......
...@@ -194,6 +194,7 @@ obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o ...@@ -194,6 +194,7 @@ obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o
obj-$(CONFIG_SENSORS_SCH5627) += sch5627.o obj-$(CONFIG_SENSORS_SCH5627) += sch5627.o
obj-$(CONFIG_SENSORS_SCH5636) += sch5636.o obj-$(CONFIG_SENSORS_SCH5636) += sch5636.o
obj-$(CONFIG_SENSORS_SFCTEMP) += sfctemp.o obj-$(CONFIG_SENSORS_SFCTEMP) += sfctemp.o
obj-$(CONFIG_SENSORS_SG2042_MCU) += sg2042-mcu.o
obj-$(CONFIG_SENSORS_SL28CPLD) += sl28cpld-hwmon.o obj-$(CONFIG_SENSORS_SL28CPLD) += sl28cpld-hwmon.o
obj-$(CONFIG_SENSORS_SHT15) += sht15.o obj-$(CONFIG_SENSORS_SHT15) += sht15.o
obj-$(CONFIG_SENSORS_SHT21) += sht21.o obj-$(CONFIG_SENSORS_SHT21) += sht21.o
...@@ -209,6 +210,7 @@ obj-$(CONFIG_SENSORS_SPARX5) += sparx5-temp.o ...@@ -209,6 +210,7 @@ obj-$(CONFIG_SENSORS_SPARX5) += sparx5-temp.o
obj-$(CONFIG_SENSORS_SPD5118) += spd5118.o obj-$(CONFIG_SENSORS_SPD5118) += spd5118.o
obj-$(CONFIG_SENSORS_STTS751) += stts751.o obj-$(CONFIG_SENSORS_STTS751) += stts751.o
obj-$(CONFIG_SENSORS_SURFACE_FAN)+= surface_fan.o obj-$(CONFIG_SENSORS_SURFACE_FAN)+= surface_fan.o
obj-$(CONFIG_SENSORS_SURFACE_TEMP)+= surface_temp.o
obj-$(CONFIG_SENSORS_SY7636A) += sy7636a-hwmon.o obj-$(CONFIG_SENSORS_SY7636A) += sy7636a-hwmon.o
obj-$(CONFIG_SENSORS_AMC6821) += amc6821.o obj-$(CONFIG_SENSORS_AMC6821) += amc6821.o
obj-$(CONFIG_SENSORS_TC74) += tc74.o obj-$(CONFIG_SENSORS_TC74) += tc74.o
......
...@@ -728,30 +728,22 @@ static const int adt7470_freq_map[] = { ...@@ -728,30 +728,22 @@ static const int adt7470_freq_map[] = {
static int pwm1_freq_get(struct device *dev) static int pwm1_freq_get(struct device *dev)
{ {
struct adt7470_data *data = dev_get_drvdata(dev); struct adt7470_data *data = dev_get_drvdata(dev);
unsigned int cfg_reg_1, cfg_reg_2; unsigned int regs[2] = {ADT7470_REG_CFG, ADT7470_REG_CFG_2};
u8 cfg_reg[2];
int index; int index;
int err; int err;
mutex_lock(&data->lock); err = regmap_multi_reg_read(data->regmap, regs, cfg_reg, 2);
err = regmap_read(data->regmap, ADT7470_REG_CFG, &cfg_reg_1); if (err)
if (err < 0) return err;
goto out;
err = regmap_read(data->regmap, ADT7470_REG_CFG_2, &cfg_reg_2);
if (err < 0)
goto out;
mutex_unlock(&data->lock);
index = (cfg_reg_2 & ADT7470_FREQ_MASK) >> ADT7470_FREQ_SHIFT; index = (cfg_reg[1] & ADT7470_FREQ_MASK) >> ADT7470_FREQ_SHIFT;
if (!(cfg_reg_1 & ADT7470_CFG_LF)) if (!(cfg_reg[0] & ADT7470_CFG_LF))
index += 8; index += 8;
if (index >= ARRAY_SIZE(adt7470_freq_map)) if (index >= ARRAY_SIZE(adt7470_freq_map))
index = ARRAY_SIZE(adt7470_freq_map) - 1; index = ARRAY_SIZE(adt7470_freq_map) - 1;
return adt7470_freq_map[index]; return adt7470_freq_map[index];
out:
mutex_unlock(&data->lock);
return err;
} }
static int adt7470_pwm_read(struct device *dev, u32 attr, int channel, long *val) static int adt7470_pwm_read(struct device *dev, u32 attr, int channel, long *val)
......
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/util_macros.h> #include <linux/util_macros.h>
#include <dt-bindings/pwm/pwm.h>
/* Indexes for the sysfs hooks */ /* Indexes for the sysfs hooks */
enum adt_sysfs_id { enum adt_sysfs_id {
INPUT = 0, INPUT = 0,
...@@ -1662,6 +1664,130 @@ static int adt7475_set_pwm_polarity(struct i2c_client *client) ...@@ -1662,6 +1664,130 @@ static int adt7475_set_pwm_polarity(struct i2c_client *client)
return 0; return 0;
} }
struct adt7475_pwm_config {
int index;
int freq;
int flags;
int duty;
};
static int _adt7475_pwm_properties_parse_args(u32 args[4], struct adt7475_pwm_config *cfg)
{
int freq_hz;
int duty;
if (args[1] == 0)
return -EINVAL;
freq_hz = 1000000000UL / args[1];
if (args[3] >= args[1])
duty = 255;
else
duty = div_u64(255ULL * args[3], args[1]);
cfg->index = args[0];
cfg->freq = find_closest(freq_hz, pwmfreq_table, ARRAY_SIZE(pwmfreq_table));
cfg->flags = args[2];
cfg->duty = duty;
return 0;
}
static int adt7475_pwm_properties_parse_reference_args(struct fwnode_handle *fwnode,
struct adt7475_pwm_config *cfg)
{
int ret, i;
struct fwnode_reference_args rargs = {};
u32 args[4] = {};
ret = fwnode_property_get_reference_args(fwnode, "pwms", "#pwm-cells", 0, 0, &rargs);
if (ret)
return ret;
if (rargs.nargs != 4) {
fwnode_handle_put(rargs.fwnode);
return -EINVAL;
}
for (i = 0; i < 4; i++)
args[i] = rargs.args[i];
ret = _adt7475_pwm_properties_parse_args(args, cfg);
fwnode_handle_put(rargs.fwnode);
return ret;
}
static int adt7475_pwm_properties_parse_args(struct fwnode_handle *fwnode,
struct adt7475_pwm_config *cfg)
{
int ret;
u32 args[4] = {};
ret = fwnode_property_read_u32_array(fwnode, "pwms", args, ARRAY_SIZE(args));
if (ret)
return ret;
return _adt7475_pwm_properties_parse_args(args, cfg);
}
static int adt7475_fan_pwm_config(struct i2c_client *client)
{
struct adt7475_data *data = i2c_get_clientdata(client);
struct fwnode_handle *child;
struct adt7475_pwm_config cfg = {};
int ret;
device_for_each_child_node(&client->dev, child) {
if (!fwnode_property_present(child, "pwms"))
continue;
if (is_of_node(child))
ret = adt7475_pwm_properties_parse_reference_args(child, &cfg);
else
ret = adt7475_pwm_properties_parse_args(child, &cfg);
if (cfg.index >= ADT7475_PWM_COUNT)
return -EINVAL;
ret = adt7475_read(PWM_CONFIG_REG(cfg.index));
if (ret < 0)
return ret;
data->pwm[CONTROL][cfg.index] = ret;
if (cfg.flags & PWM_POLARITY_INVERTED)
data->pwm[CONTROL][cfg.index] |= BIT(4);
else
data->pwm[CONTROL][cfg.index] &= ~BIT(4);
/* Force to manual mode so PWM values take effect */
data->pwm[CONTROL][cfg.index] &= ~0xE0;
data->pwm[CONTROL][cfg.index] |= 0x07 << 5;
ret = i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(cfg.index),
data->pwm[CONTROL][cfg.index]);
if (ret)
return ret;
data->pwm[INPUT][cfg.index] = cfg.duty;
ret = i2c_smbus_write_byte_data(client, PWM_REG(cfg.index),
data->pwm[INPUT][cfg.index]);
if (ret)
return ret;
data->range[cfg.index] = adt7475_read(TEMP_TRANGE_REG(cfg.index));
data->range[cfg.index] &= ~0xf;
data->range[cfg.index] |= cfg.freq;
ret = i2c_smbus_write_byte_data(client, TEMP_TRANGE_REG(cfg.index),
data->range[cfg.index]);
if (ret)
return ret;
}
return 0;
}
static int adt7475_probe(struct i2c_client *client) static int adt7475_probe(struct i2c_client *client)
{ {
enum chips chip; enum chips chip;
...@@ -1774,6 +1900,10 @@ static int adt7475_probe(struct i2c_client *client) ...@@ -1774,6 +1900,10 @@ static int adt7475_probe(struct i2c_client *client)
if (ret && ret != -EINVAL) if (ret && ret != -EINVAL)
dev_warn(&client->dev, "Error configuring pwm polarity\n"); dev_warn(&client->dev, "Error configuring pwm polarity\n");
ret = adt7475_fan_pwm_config(client);
if (ret)
dev_warn(&client->dev, "Error %d configuring fan/pwm\n", ret);
/* Start monitoring */ /* Start monitoring */
switch (chip) { switch (chip) {
case adt7475: case adt7475:
......
...@@ -170,21 +170,15 @@ static int adt7x10_temp_write(struct adt7x10_data *data, int index, long temp) ...@@ -170,21 +170,15 @@ static int adt7x10_temp_write(struct adt7x10_data *data, int index, long temp)
static int adt7x10_hyst_read(struct adt7x10_data *data, int index, long *val) static int adt7x10_hyst_read(struct adt7x10_data *data, int index, long *val)
{ {
int hyst, temp, ret; unsigned int regs[2] = {ADT7X10_T_HYST, ADT7X10_REG_TEMP[index]};
int hyst, ret;
u16 regdata[2];
mutex_lock(&data->update_lock); ret = regmap_multi_reg_read(data->regmap, regs, regdata, 2);
ret = regmap_read(data->regmap, ADT7X10_T_HYST, &hyst);
if (ret) {
mutex_unlock(&data->update_lock);
return ret;
}
ret = regmap_read(data->regmap, ADT7X10_REG_TEMP[index], &temp);
mutex_unlock(&data->update_lock);
if (ret) if (ret)
return ret; return ret;
hyst = (hyst & ADT7X10_T_HYST_MASK) * 1000; hyst = (regdata[0] & ADT7X10_T_HYST_MASK) * 1000;
/* /*
* hysteresis is stored as a 4 bit offset in the device, convert it * hysteresis is stored as a 4 bit offset in the device, convert it
...@@ -194,7 +188,7 @@ static int adt7x10_hyst_read(struct adt7x10_data *data, int index, long *val) ...@@ -194,7 +188,7 @@ static int adt7x10_hyst_read(struct adt7x10_data *data, int index, long *val)
if (index == adt7x10_t_alarm_low) if (index == adt7x10_t_alarm_low)
hyst = -hyst; hyst = -hyst;
*val = ADT7X10_REG_TO_TEMP(data, temp) - hyst; *val = ADT7X10_REG_TO_TEMP(data, regdata[1]) - hyst;
return 0; return 0;
} }
......
...@@ -136,29 +136,25 @@ struct amc6821_data { ...@@ -136,29 +136,25 @@ struct amc6821_data {
*/ */
static int amc6821_get_auto_point_temps(struct regmap *regmap, int channel, u8 *temps) static int amc6821_get_auto_point_temps(struct regmap *regmap, int channel, u8 *temps)
{ {
u32 pwm, regval; u32 regs[] = {
AMC6821_REG_DCY_LOW_TEMP,
AMC6821_REG_PSV_TEMP,
channel ? AMC6821_REG_RTEMP_FAN_CTRL : AMC6821_REG_LTEMP_FAN_CTRL
};
u8 regvals[3];
int slope;
int err; int err;
err = regmap_read(regmap, AMC6821_REG_DCY_LOW_TEMP, &pwm); err = regmap_multi_reg_read(regmap, regs, regvals, 3);
if (err)
return err;
err = regmap_read(regmap, AMC6821_REG_PSV_TEMP, &regval);
if (err)
return err;
temps[0] = regval;
err = regmap_read(regmap,
channel ? AMC6821_REG_RTEMP_FAN_CTRL : AMC6821_REG_LTEMP_FAN_CTRL,
&regval);
if (err) if (err)
return err; return err;
temps[1] = FIELD_GET(AMC6821_TEMP_LIMIT_MASK, regval) * 4; temps[0] = regvals[1];
temps[1] = FIELD_GET(AMC6821_TEMP_LIMIT_MASK, regvals[2]) * 4;
/* slope is 32 >> <slope bits> in °C */ /* slope is 32 >> <slope bits> in °C */
regval = 32 >> FIELD_GET(AMC6821_TEMP_SLOPE_MASK, regval); slope = 32 >> FIELD_GET(AMC6821_TEMP_SLOPE_MASK, regvals[2]);
if (regval) if (slope)
temps[2] = temps[1] + DIV_ROUND_CLOSEST(255 - pwm, regval); temps[2] = temps[1] + DIV_ROUND_CLOSEST(255 - regvals[0], slope);
else else
temps[2] = 255; temps[2] = 255;
......
...@@ -456,7 +456,6 @@ static int aspeed_pwm_tach_probe(struct platform_device *pdev) ...@@ -456,7 +456,6 @@ static int aspeed_pwm_tach_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev, *hwmon; struct device *dev = &pdev->dev, *hwmon;
int ret; int ret;
struct device_node *child;
struct aspeed_pwm_tach_data *priv; struct aspeed_pwm_tach_data *priv;
struct pwm_chip *chip; struct pwm_chip *chip;
...@@ -498,10 +497,9 @@ static int aspeed_pwm_tach_probe(struct platform_device *pdev) ...@@ -498,10 +497,9 @@ static int aspeed_pwm_tach_probe(struct platform_device *pdev)
if (ret) if (ret)
return dev_err_probe(dev, ret, "Failed to add PWM chip\n"); return dev_err_probe(dev, ret, "Failed to add PWM chip\n");
for_each_child_of_node(dev->of_node, child) { for_each_child_of_node_scoped(dev->of_node, child) {
ret = aspeed_create_fan_monitor(dev, child, priv); ret = aspeed_create_fan_monitor(dev, child, priv);
if (ret) { if (ret) {
of_node_put(child);
dev_warn(dev, "Failed to create fan %d", ret); dev_warn(dev, "Failed to create fan %d", ret);
return 0; return 0;
} }
......
...@@ -907,7 +907,7 @@ static void aspeed_pwm_tacho_remove(void *data) ...@@ -907,7 +907,7 @@ static void aspeed_pwm_tacho_remove(void *data)
static int aspeed_pwm_tacho_probe(struct platform_device *pdev) static int aspeed_pwm_tacho_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *np, *child; struct device_node *np;
struct aspeed_pwm_tacho_data *priv; struct aspeed_pwm_tacho_data *priv;
void __iomem *regs; void __iomem *regs;
struct device *hwmon; struct device *hwmon;
...@@ -951,12 +951,10 @@ static int aspeed_pwm_tacho_probe(struct platform_device *pdev) ...@@ -951,12 +951,10 @@ static int aspeed_pwm_tacho_probe(struct platform_device *pdev)
aspeed_create_type(priv); aspeed_create_type(priv);
for_each_child_of_node(np, child) { for_each_child_of_node_scoped(np, child) {
ret = aspeed_create_fan(dev, child, priv); ret = aspeed_create_fan(dev, child, priv);
if (ret) { if (ret)
of_node_put(child);
return ret; return ret;
}
} }
priv->groups[0] = &pwm_dev_group; priv->groups[0] = &pwm_dev_group;
......
...@@ -740,37 +740,26 @@ static int cc2_probe(struct i2c_client *client) ...@@ -740,37 +740,26 @@ static int cc2_probe(struct i2c_client *client)
data->client = client; data->client = client;
data->regulator = devm_regulator_get_exclusive(dev, "vdd"); data->regulator = devm_regulator_get_exclusive(dev, "vdd");
if (IS_ERR(data->regulator)) { if (IS_ERR(data->regulator))
dev_err_probe(dev, PTR_ERR(data->regulator), return dev_err_probe(dev, PTR_ERR(data->regulator),
"Failed to get regulator\n"); "Failed to get regulator\n");
return PTR_ERR(data->regulator);
}
ret = cc2_request_ready_irq(data, dev); ret = cc2_request_ready_irq(data, dev);
if (ret) { if (ret)
dev_err_probe(dev, ret, "Failed to request ready irq\n"); return dev_err_probe(dev, ret, "Failed to request ready irq\n");
return ret;
}
ret = cc2_request_alarm_irqs(data, dev); ret = cc2_request_alarm_irqs(data, dev);
if (ret) { if (ret)
dev_err_probe(dev, ret, "Failed to request alarm irqs\n"); return dev_err_probe(dev, ret, "Failed to request alarm irqs\n");
goto disable;
}
data->hwmon = devm_hwmon_device_register_with_info(dev, client->name, data->hwmon = devm_hwmon_device_register_with_info(dev, client->name,
data, &cc2_chip_info, data, &cc2_chip_info,
NULL); NULL);
if (IS_ERR(data->hwmon)) { if (IS_ERR(data->hwmon))
dev_err_probe(dev, PTR_ERR(data->hwmon), return dev_err_probe(dev, PTR_ERR(data->hwmon),
"Failed to register hwmon device\n"); "Failed to register hwmon device\n");
ret = PTR_ERR(data->hwmon);
}
disable:
cc2_disable(data);
return ret; return 0;
} }
static void cc2_remove(struct i2c_client *client) static void cc2_remove(struct i2c_client *client)
......
...@@ -1488,6 +1488,14 @@ static const struct dmi_system_id i8k_whitelist_fan_control[] __initconst = { ...@@ -1488,6 +1488,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 Latitude 7320",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Latitude 7320"),
},
.driver_data = (void *)&i8k_fan_control_data[I8K_FAN_30A3_31A3],
},
{ {
.ident = "Dell Latitude E6440", .ident = "Dell Latitude E6440",
.matches = { .matches = {
......
...@@ -400,6 +400,7 @@ static const struct of_device_id gsc_hwmon_of_match[] = { ...@@ -400,6 +400,7 @@ static const struct of_device_id gsc_hwmon_of_match[] = {
{ .compatible = "gw,gsc-adc", }, { .compatible = "gw,gsc-adc", },
{} {}
}; };
MODULE_DEVICE_TABLE(of, gsc_hwmon_of_match);
static struct platform_driver gsc_hwmon_driver = { static struct platform_driver gsc_hwmon_driver = {
.driver = { .driver = {
......
...@@ -1188,24 +1188,6 @@ devm_hwmon_device_register_with_info(struct device *dev, const char *name, ...@@ -1188,24 +1188,6 @@ devm_hwmon_device_register_with_info(struct device *dev, const char *name,
} }
EXPORT_SYMBOL_GPL(devm_hwmon_device_register_with_info); EXPORT_SYMBOL_GPL(devm_hwmon_device_register_with_info);
static int devm_hwmon_match(struct device *dev, void *res, void *data)
{
struct device **hwdev = res;
return *hwdev == data;
}
/**
* devm_hwmon_device_unregister - removes a previously registered hwmon device
*
* @dev: the parent device of the device to unregister
*/
void devm_hwmon_device_unregister(struct device *dev)
{
WARN_ON(devres_release(dev, devm_hwmon_release, devm_hwmon_match, dev));
}
EXPORT_SYMBOL_GPL(devm_hwmon_device_unregister);
static char *__hwmon_sanitize_name(struct device *dev, const char *old_name) static char *__hwmon_sanitize_name(struct device *dev, const char *old_name)
{ {
char *name, *p; char *name, *p;
......
This diff is collapsed.
...@@ -813,7 +813,6 @@ static int ina3221_probe_child_from_dt(struct device *dev, ...@@ -813,7 +813,6 @@ static int ina3221_probe_child_from_dt(struct device *dev,
static int ina3221_probe_from_dt(struct device *dev, struct ina3221_data *ina) static int ina3221_probe_from_dt(struct device *dev, struct ina3221_data *ina)
{ {
const struct device_node *np = dev->of_node; const struct device_node *np = dev->of_node;
struct device_node *child;
int ret; int ret;
/* Compatible with non-DT platforms */ /* Compatible with non-DT platforms */
...@@ -822,12 +821,10 @@ static int ina3221_probe_from_dt(struct device *dev, struct ina3221_data *ina) ...@@ -822,12 +821,10 @@ static int ina3221_probe_from_dt(struct device *dev, struct ina3221_data *ina)
ina->single_shot = of_property_read_bool(np, "ti,single-shot"); ina->single_shot = of_property_read_bool(np, "ti,single-shot");
for_each_child_of_node(np, child) { for_each_child_of_node_scoped(np, child) {
ret = ina3221_probe_child_from_dt(dev, child, ina); ret = ina3221_probe_child_from_dt(dev, child, ina);
if (ret) { if (ret)
of_node_put(child);
return ret; return ret;
}
} }
return 0; return 0;
......
...@@ -438,16 +438,21 @@ static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -438,16 +438,21 @@ static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
data->disp_negative = true; data->disp_negative = true;
} }
if (boot_cpu_data.x86 == 0x15 && data->is_zen = cpu_feature_enabled(X86_FEATURE_ZEN);
if (data->is_zen) {
data->temp_adjust_mask = ZEN_CUR_TEMP_RANGE_SEL_MASK;
data->read_tempreg = read_tempreg_nb_zen;
} else if (boot_cpu_data.x86 == 0x15 &&
((boot_cpu_data.x86_model & 0xf0) == 0x60 || ((boot_cpu_data.x86_model & 0xf0) == 0x60 ||
(boot_cpu_data.x86_model & 0xf0) == 0x70)) { (boot_cpu_data.x86_model & 0xf0) == 0x70)) {
data->read_htcreg = read_htcreg_nb_f15; data->read_htcreg = read_htcreg_nb_f15;
data->read_tempreg = read_tempreg_nb_f15; data->read_tempreg = read_tempreg_nb_f15;
} else if (boot_cpu_data.x86 == 0x17 || boot_cpu_data.x86 == 0x18) { } else {
data->temp_adjust_mask = ZEN_CUR_TEMP_RANGE_SEL_MASK; data->read_htcreg = read_htcreg_pci;
data->read_tempreg = read_tempreg_nb_zen; data->read_tempreg = read_tempreg_pci;
data->is_zen = true; }
if (boot_cpu_data.x86 == 0x17 || boot_cpu_data.x86 == 0x18) {
switch (boot_cpu_data.x86_model) { switch (boot_cpu_data.x86_model) {
case 0x1: /* Zen */ case 0x1: /* Zen */
case 0x8: /* Zen+ */ case 0x8: /* Zen+ */
...@@ -469,10 +474,6 @@ static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -469,10 +474,6 @@ static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
break; break;
} }
} else if (boot_cpu_data.x86 == 0x19) { } else if (boot_cpu_data.x86 == 0x19) {
data->temp_adjust_mask = ZEN_CUR_TEMP_RANGE_SEL_MASK;
data->read_tempreg = read_tempreg_nb_zen;
data->is_zen = true;
switch (boot_cpu_data.x86_model) { switch (boot_cpu_data.x86_model) {
case 0x0 ... 0x1: /* Zen3 SP3/TR */ case 0x0 ... 0x1: /* Zen3 SP3/TR */
case 0x8: /* Zen3 TR Chagall */ case 0x8: /* Zen3 TR Chagall */
...@@ -496,13 +497,6 @@ static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -496,13 +497,6 @@ static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
k10temp_get_ccd_support(data, 12); k10temp_get_ccd_support(data, 12);
break; break;
} }
} else if (boot_cpu_data.x86 == 0x1a) {
data->temp_adjust_mask = ZEN_CUR_TEMP_RANGE_SEL_MASK;
data->read_tempreg = read_tempreg_nb_zen;
data->is_zen = true;
} else {
data->read_htcreg = read_htcreg_pci;
data->read_tempreg = read_tempreg_pci;
} }
for (i = 0; i < ARRAY_SIZE(tctl_offset_table); i++) { for (i = 0; i < ARRAY_SIZE(tctl_offset_table); i++) {
......
...@@ -2674,19 +2674,16 @@ static int lm90_parse_dt_channel_info(struct i2c_client *client, ...@@ -2674,19 +2674,16 @@ static int lm90_parse_dt_channel_info(struct i2c_client *client,
struct lm90_data *data) struct lm90_data *data)
{ {
int err; int err;
struct device_node *child;
struct device *dev = &client->dev; struct device *dev = &client->dev;
const struct device_node *np = dev->of_node; const struct device_node *np = dev->of_node;
for_each_child_of_node(np, child) { for_each_child_of_node_scoped(np, child) {
if (strcmp(child->name, "channel")) if (strcmp(child->name, "channel"))
continue; continue;
err = lm90_probe_channel_from_dt(client, child, data); err = lm90_probe_channel_from_dt(client, child, data);
if (err) { if (err)
of_node_put(child);
return err; return err;
}
} }
return 0; return 0;
......
This diff is collapsed.
This diff is collapsed.
...@@ -161,18 +161,18 @@ static int lm95245_read_temp(struct device *dev, u32 attr, int channel, ...@@ -161,18 +161,18 @@ static int lm95245_read_temp(struct device *dev, u32 attr, int channel,
{ {
struct lm95245_data *data = dev_get_drvdata(dev); struct lm95245_data *data = dev_get_drvdata(dev);
struct regmap *regmap = data->regmap; struct regmap *regmap = data->regmap;
int ret, regl, regh, regvall, regvalh; unsigned int regs[2];
unsigned int regval;
u8 regvals[2];
int ret;
switch (attr) { switch (attr) {
case hwmon_temp_input: case hwmon_temp_input:
regl = channel ? LM95245_REG_R_REMOTE_TEMPL_S : regs[0] = channel ? LM95245_REG_R_REMOTE_TEMPL_S :
LM95245_REG_R_LOCAL_TEMPL_S; LM95245_REG_R_LOCAL_TEMPL_S;
regh = channel ? LM95245_REG_R_REMOTE_TEMPH_S : regs[1] = channel ? LM95245_REG_R_REMOTE_TEMPH_S :
LM95245_REG_R_LOCAL_TEMPH_S; LM95245_REG_R_LOCAL_TEMPH_S;
ret = regmap_read(regmap, regl, &regvall); ret = regmap_multi_reg_read(regmap, regs, regvals, 2);
if (ret < 0)
return ret;
ret = regmap_read(regmap, regh, &regvalh);
if (ret < 0) if (ret < 0)
return ret; return ret;
/* /*
...@@ -181,92 +181,77 @@ static int lm95245_read_temp(struct device *dev, u32 attr, int channel, ...@@ -181,92 +181,77 @@ static int lm95245_read_temp(struct device *dev, u32 attr, int channel,
* Use signed calculation for remote if signed bit is set * Use signed calculation for remote if signed bit is set
* or if reported temperature is below signed limit. * or if reported temperature is below signed limit.
*/ */
if (!channel || (regvalh & 0x80) || regvalh < 0x7f) { if (!channel || (regvals[1] & 0x80) || regvals[1] < 0x7f) {
*val = temp_from_reg_signed(regvalh, regvall); *val = temp_from_reg_signed(regvals[1], regvals[0]);
return 0; return 0;
} }
ret = regmap_read(regmap, LM95245_REG_R_REMOTE_TEMPL_U, ret = regmap_bulk_read(regmap, LM95245_REG_R_REMOTE_TEMPH_U, regvals, 2);
&regvall); if (ret)
if (ret < 0)
return ret;
ret = regmap_read(regmap, LM95245_REG_R_REMOTE_TEMPH_U,
&regvalh);
if (ret < 0)
return ret; return ret;
*val = temp_from_reg_unsigned(regvalh, regvall); *val = temp_from_reg_unsigned(regvals[0], regvals[1]);
return 0; return 0;
case hwmon_temp_max: case hwmon_temp_max:
ret = regmap_read(regmap, LM95245_REG_RW_REMOTE_OS_LIMIT, ret = regmap_read(regmap, LM95245_REG_RW_REMOTE_OS_LIMIT,
&regvalh); &regval);
if (ret < 0) if (ret < 0)
return ret; return ret;
*val = regvalh * 1000; *val = regval * 1000;
return 0; return 0;
case hwmon_temp_crit: case hwmon_temp_crit:
regh = channel ? LM95245_REG_RW_REMOTE_TCRIT_LIMIT : regs[0] = channel ? LM95245_REG_RW_REMOTE_TCRIT_LIMIT :
LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT; LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT;
ret = regmap_read(regmap, regh, &regvalh); ret = regmap_read(regmap, regs[0], &regval);
if (ret < 0) if (ret < 0)
return ret; return ret;
*val = regvalh * 1000; *val = regval * 1000;
return 0; return 0;
case hwmon_temp_max_hyst: case hwmon_temp_max_hyst:
ret = regmap_read(regmap, LM95245_REG_RW_REMOTE_OS_LIMIT, regs[0] = LM95245_REG_RW_REMOTE_OS_LIMIT;
&regvalh); regs[1] = LM95245_REG_RW_COMMON_HYSTERESIS;
ret = regmap_multi_reg_read(regmap, regs, regvals, 2);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = regmap_read(regmap, LM95245_REG_RW_COMMON_HYSTERESIS, *val = (regvals[0] - regvals[1]) * 1000;
&regvall);
if (ret < 0)
return ret;
*val = (regvalh - regvall) * 1000;
return 0; return 0;
case hwmon_temp_crit_hyst: case hwmon_temp_crit_hyst:
regh = channel ? LM95245_REG_RW_REMOTE_TCRIT_LIMIT : regs[0] = channel ? LM95245_REG_RW_REMOTE_TCRIT_LIMIT :
LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT; LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT;
ret = regmap_read(regmap, regh, &regvalh); regs[1] = LM95245_REG_RW_COMMON_HYSTERESIS;
if (ret < 0)
return ret; ret = regmap_multi_reg_read(regmap, regs, regvals, 2);
ret = regmap_read(regmap, LM95245_REG_RW_COMMON_HYSTERESIS,
&regvall);
if (ret < 0) if (ret < 0)
return ret; return ret;
*val = (regvalh - regvall) * 1000; *val = (regvals[0] - regvals[1]) * 1000;
return 0; return 0;
case hwmon_temp_type: case hwmon_temp_type:
ret = regmap_read(regmap, LM95245_REG_RW_CONFIG2, &regvalh); ret = regmap_read(regmap, LM95245_REG_RW_CONFIG2, &regval);
if (ret < 0) if (ret < 0)
return ret; return ret;
*val = (regvalh & CFG2_REMOTE_TT) ? 1 : 2; *val = (regval & CFG2_REMOTE_TT) ? 1 : 2;
return 0; return 0;
case hwmon_temp_offset: case hwmon_temp_offset:
ret = regmap_read(regmap, LM95245_REG_RW_REMOTE_OFFL, ret = regmap_bulk_read(regmap, LM95245_REG_RW_REMOTE_OFFH, regvals, 2);
&regvall);
if (ret < 0)
return ret;
ret = regmap_read(regmap, LM95245_REG_RW_REMOTE_OFFH,
&regvalh);
if (ret < 0) if (ret < 0)
return ret; return ret;
*val = temp_from_reg_signed(regvalh, regvall); *val = temp_from_reg_signed(regvals[0], regvals[1]);
return 0; return 0;
case hwmon_temp_max_alarm: case hwmon_temp_max_alarm:
ret = regmap_read(regmap, LM95245_REG_R_STATUS1, &regvalh); ret = regmap_read(regmap, LM95245_REG_R_STATUS1, &regval);
if (ret < 0) if (ret < 0)
return ret; return ret;
*val = !!(regvalh & STATUS1_ROS); *val = !!(regval & STATUS1_ROS);
return 0; return 0;
case hwmon_temp_crit_alarm: case hwmon_temp_crit_alarm:
ret = regmap_read(regmap, LM95245_REG_R_STATUS1, &regvalh); ret = regmap_read(regmap, LM95245_REG_R_STATUS1, &regval);
if (ret < 0) if (ret < 0)
return ret; return ret;
*val = !!(regvalh & (channel ? STATUS1_RTCRIT : STATUS1_LOC)); *val = !!(regval & (channel ? STATUS1_RTCRIT : STATUS1_LOC));
return 0; return 0;
case hwmon_temp_fault: case hwmon_temp_fault:
ret = regmap_read(regmap, LM95245_REG_R_STATUS1, &regvalh); ret = regmap_read(regmap, LM95245_REG_R_STATUS1, &regval);
if (ret < 0) if (ret < 0)
return ret; return ret;
*val = !!(regvalh & STATUS1_DIODE_FAULT); *val = !!(regval & STATUS1_DIODE_FAULT);
return 0; return 0;
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -279,6 +264,7 @@ static int lm95245_write_temp(struct device *dev, u32 attr, int channel, ...@@ -279,6 +264,7 @@ static int lm95245_write_temp(struct device *dev, u32 attr, int channel,
struct lm95245_data *data = dev_get_drvdata(dev); struct lm95245_data *data = dev_get_drvdata(dev);
struct regmap *regmap = data->regmap; struct regmap *regmap = data->regmap;
unsigned int regval; unsigned int regval;
u8 regvals[2];
int ret, reg; int ret, reg;
switch (attr) { switch (attr) {
...@@ -311,16 +297,10 @@ static int lm95245_write_temp(struct device *dev, u32 attr, int channel, ...@@ -311,16 +297,10 @@ static int lm95245_write_temp(struct device *dev, u32 attr, int channel,
case hwmon_temp_offset: case hwmon_temp_offset:
val = clamp_val(val, -128000, 127875); val = clamp_val(val, -128000, 127875);
val = val * 256 / 1000; val = val * 256 / 1000;
mutex_lock(&data->update_lock); regvals[0] = val >> 8;
ret = regmap_write(regmap, LM95245_REG_RW_REMOTE_OFFL, regvals[1] = val & 0xe0;
val & 0xe0);
if (ret < 0) { ret = regmap_bulk_write(regmap, LM95245_REG_RW_REMOTE_OFFH, regvals, 2);
mutex_unlock(&data->update_lock);
return ret;
}
ret = regmap_write(regmap, LM95245_REG_RW_REMOTE_OFFH,
(val >> 8) & 0xff);
mutex_unlock(&data->update_lock);
return ret; return ret;
case hwmon_temp_type: case hwmon_temp_type:
if (val != 1 && val != 2) if (val != 1 && val != 2)
......
...@@ -11,7 +11,8 @@ ...@@ -11,7 +11,8 @@
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h> #include <linux/hwmon-sysfs.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/mod_devicetable.h>
#include <linux/property.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include "ltc2947.h" #include "ltc2947.h"
...@@ -1034,9 +1035,8 @@ static int ltc2947_setup(struct ltc2947_data *st) ...@@ -1034,9 +1035,8 @@ static int ltc2947_setup(struct ltc2947_data *st)
/* 19.89E-6 * 10E9 */ /* 19.89E-6 * 10E9 */
st->lsb_energy = 19890; st->lsb_energy = 19890;
} }
ret = of_property_read_u32_array(st->dev->of_node, ret = device_property_read_u32_array(st->dev, "adi,accumulator-ctl-pol",
"adi,accumulator-ctl-pol", accum, accum, ARRAY_SIZE(accum));
ARRAY_SIZE(accum));
if (!ret) { if (!ret) {
u32 accum_reg = LTC2947_ACCUM_POL_1(accum[0]) | u32 accum_reg = LTC2947_ACCUM_POL_1(accum[0]) |
LTC2947_ACCUM_POL_2(accum[1]); LTC2947_ACCUM_POL_2(accum[1]);
...@@ -1045,9 +1045,9 @@ static int ltc2947_setup(struct ltc2947_data *st) ...@@ -1045,9 +1045,9 @@ static int ltc2947_setup(struct ltc2947_data *st)
if (ret) if (ret)
return ret; return ret;
} }
ret = of_property_read_u32(st->dev->of_node, ret = device_property_read_u32(st->dev,
"adi,accumulation-deadband-microamp", "adi,accumulation-deadband-microamp",
&deadband); &deadband);
if (!ret) { if (!ret) {
/* the LSB is the same as the current, so 3mA */ /* the LSB is the same as the current, so 3mA */
ret = regmap_write(st->map, LTC2947_REG_ACCUM_DEADBAND, ret = regmap_write(st->map, LTC2947_REG_ACCUM_DEADBAND,
...@@ -1056,7 +1056,7 @@ static int ltc2947_setup(struct ltc2947_data *st) ...@@ -1056,7 +1056,7 @@ static int ltc2947_setup(struct ltc2947_data *st)
return ret; return ret;
} }
/* check gpio cfg */ /* check gpio cfg */
ret = of_property_read_u32(st->dev->of_node, "adi,gpio-out-pol", &pol); ret = device_property_read_u32(st->dev, "adi,gpio-out-pol", &pol);
if (!ret) { if (!ret) {
/* setup GPIO as output */ /* setup GPIO as output */
u32 gpio_ctl = LTC2947_GPIO_EN(1) | LTC2947_GPIO_FAN_EN(1) | u32 gpio_ctl = LTC2947_GPIO_EN(1) | LTC2947_GPIO_FAN_EN(1) |
...@@ -1067,8 +1067,8 @@ static int ltc2947_setup(struct ltc2947_data *st) ...@@ -1067,8 +1067,8 @@ static int ltc2947_setup(struct ltc2947_data *st)
if (ret) if (ret)
return ret; return ret;
} }
ret = of_property_read_u32_array(st->dev->of_node, "adi,gpio-in-accum", ret = device_property_read_u32_array(st->dev, "adi,gpio-in-accum",
accum, ARRAY_SIZE(accum)); accum, ARRAY_SIZE(accum));
if (!ret) { if (!ret) {
/* /*
* Setup the accum options. The gpioctl is already defined as * Setup the accum options. The gpioctl is already defined as
......
...@@ -854,33 +854,24 @@ static const struct regmap_config ltc2992_regmap_config = { ...@@ -854,33 +854,24 @@ static const struct regmap_config ltc2992_regmap_config = {
static int ltc2992_parse_dt(struct ltc2992_state *st) static int ltc2992_parse_dt(struct ltc2992_state *st)
{ {
struct fwnode_handle *fwnode;
struct fwnode_handle *child;
u32 addr; u32 addr;
u32 val; u32 val;
int ret; int ret;
fwnode = dev_fwnode(&st->client->dev); device_for_each_child_node_scoped(&st->client->dev, child) {
fwnode_for_each_available_child_node(fwnode, child) {
ret = fwnode_property_read_u32(child, "reg", &addr); ret = fwnode_property_read_u32(child, "reg", &addr);
if (ret < 0) { if (ret < 0)
fwnode_handle_put(child);
return ret; return ret;
}
if (addr > 1) { if (addr > 1)
fwnode_handle_put(child);
return -EINVAL; return -EINVAL;
}
ret = fwnode_property_read_u32(child, "shunt-resistor-micro-ohms", &val); ret = fwnode_property_read_u32(child, "shunt-resistor-micro-ohms", &val);
if (!ret) { if (!ret) {
if (!val) { if (!val)
fwnode_handle_put(child);
return dev_err_probe(&st->client->dev, -EINVAL, return dev_err_probe(&st->client->dev, -EINVAL,
"shunt resistor value cannot be zero\n"); "shunt resistor value cannot be zero\n");
}
st->r_sense_uohm[addr] = val; st->r_sense_uohm[addr] = val;
} }
} }
......
...@@ -79,7 +79,7 @@ static const bool max16065_have_current[] = { ...@@ -79,7 +79,7 @@ static const bool max16065_have_current[] = {
}; };
struct max16065_data { struct max16065_data {
enum chips type; enum chips chip;
struct i2c_client *client; struct i2c_client *client;
const struct attribute_group *groups[4]; const struct attribute_group *groups[4];
struct mutex update_lock; struct mutex update_lock;
...@@ -114,9 +114,10 @@ static inline int LIMIT_TO_MV(int limit, int range) ...@@ -114,9 +114,10 @@ static inline int LIMIT_TO_MV(int limit, int range)
return limit * range / 256; return limit * range / 256;
} }
static inline int MV_TO_LIMIT(int mv, int range) static inline int MV_TO_LIMIT(unsigned long mv, int range)
{ {
return clamp_val(DIV_ROUND_CLOSEST(mv * 256, range), 0, 255); mv = clamp_val(mv, 0, ULONG_MAX / 256);
return DIV_ROUND_CLOSEST(clamp_val(mv * 256, 0, range * 255), range);
} }
static inline int ADC_TO_CURR(int adc, int gain) static inline int ADC_TO_CURR(int adc, int gain)
...@@ -161,10 +162,17 @@ static struct max16065_data *max16065_update_device(struct device *dev) ...@@ -161,10 +162,17 @@ static struct max16065_data *max16065_update_device(struct device *dev)
MAX16065_CURR_SENSE); MAX16065_CURR_SENSE);
} }
for (i = 0; i < DIV_ROUND_UP(data->num_adc, 8); i++) for (i = 0; i < 2; i++)
data->fault[i] data->fault[i]
= i2c_smbus_read_byte_data(client, MAX16065_FAULT(i)); = i2c_smbus_read_byte_data(client, MAX16065_FAULT(i));
/*
* MAX16067 and MAX16068 have separate undervoltage and
* overvoltage alarm bits. Squash them together.
*/
if (data->chip == max16067 || data->chip == max16068)
data->fault[0] |= data->fault[1];
data->last_updated = jiffies; data->last_updated = jiffies;
data->valid = true; data->valid = true;
} }
...@@ -513,6 +521,7 @@ static int max16065_probe(struct i2c_client *client) ...@@ -513,6 +521,7 @@ static int max16065_probe(struct i2c_client *client)
if (unlikely(!data)) if (unlikely(!data))
return -ENOMEM; return -ENOMEM;
data->chip = chip;
data->client = client; data->client = client;
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
......
This diff is collapsed.
This diff is collapsed.
...@@ -88,25 +88,16 @@ struct max6639_data { ...@@ -88,25 +88,16 @@ struct max6639_data {
static int max6639_temp_read_input(struct device *dev, int channel, long *temp) static int max6639_temp_read_input(struct device *dev, int channel, long *temp)
{ {
u32 regs[2] = { MAX6639_REG_TEMP_EXT(channel), MAX6639_REG_TEMP(channel) };
struct max6639_data *data = dev_get_drvdata(dev); struct max6639_data *data = dev_get_drvdata(dev);
unsigned int val; u8 regvals[2];
int res; int res;
/* res = regmap_multi_reg_read(data->regmap, regs, regvals, 2);
* Lock isn't needed as MAX6639_REG_TEMP wpnt change for at least 250ms after reading
* MAX6639_REG_TEMP_EXT
*/
res = regmap_read(data->regmap, MAX6639_REG_TEMP_EXT(channel), &val);
if (res < 0)
return res;
*temp = val >> 5;
res = regmap_read(data->regmap, MAX6639_REG_TEMP(channel), &val);
if (res < 0) if (res < 0)
return res; return res;
*temp |= val << 3; *temp = ((regvals[0] >> 5) | (regvals[1] << 3)) * 125;
*temp *= 125;
return 0; return 0;
} }
...@@ -290,8 +281,10 @@ static umode_t max6639_fan_is_visible(const void *_data, u32 attr, int channel) ...@@ -290,8 +281,10 @@ static umode_t max6639_fan_is_visible(const void *_data, u32 attr, int channel)
static int max6639_read_pwm(struct device *dev, u32 attr, int channel, static int max6639_read_pwm(struct device *dev, u32 attr, int channel,
long *pwm_val) long *pwm_val)
{ {
u32 regs[2] = { MAX6639_REG_FAN_CONFIG3(channel), MAX6639_REG_GCONFIG };
struct max6639_data *data = dev_get_drvdata(dev); struct max6639_data *data = dev_get_drvdata(dev);
unsigned int val; unsigned int val;
u8 regvals[2];
int res; int res;
u8 i; u8 i;
...@@ -303,26 +296,13 @@ static int max6639_read_pwm(struct device *dev, u32 attr, int channel, ...@@ -303,26 +296,13 @@ static int max6639_read_pwm(struct device *dev, u32 attr, int channel,
*pwm_val = val * 255 / 120; *pwm_val = val * 255 / 120;
return 0; return 0;
case hwmon_pwm_freq: case hwmon_pwm_freq:
mutex_lock(&data->update_lock); res = regmap_multi_reg_read(data->regmap, regs, regvals, 2);
res = regmap_read(data->regmap, MAX6639_REG_FAN_CONFIG3(channel), &val); if (res < 0)
if (res < 0) {
mutex_unlock(&data->update_lock);
return res;
}
i = val & MAX6639_FAN_CONFIG3_FREQ_MASK;
res = regmap_read(data->regmap, MAX6639_REG_GCONFIG, &val);
if (res < 0) {
mutex_unlock(&data->update_lock);
return res; return res;
} i = regvals[0] & MAX6639_FAN_CONFIG3_FREQ_MASK;
if (regvals[1] & MAX6639_GCONFIG_PWM_FREQ_HI)
if (val & MAX6639_GCONFIG_PWM_FREQ_HI)
i |= 0x4; i |= 0x4;
i &= 0x7;
*pwm_val = freq_table[i]; *pwm_val = freq_table[i];
mutex_unlock(&data->update_lock);
return 0; return 0;
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
......
This diff is collapsed.
...@@ -1269,6 +1269,7 @@ static const char * const asus_msi_boards[] = { ...@@ -1269,6 +1269,7 @@ static const char * const asus_msi_boards[] = {
"EX-B760M-V5 D4", "EX-B760M-V5 D4",
"EX-H510M-V3", "EX-H510M-V3",
"EX-H610M-V3 D4", "EX-H610M-V3 D4",
"G15CF",
"PRIME A620M-A", "PRIME A620M-A",
"PRIME B560-PLUS", "PRIME B560-PLUS",
"PRIME B560-PLUS AC-HES", "PRIME B560-PLUS AC-HES",
......
...@@ -229,41 +229,34 @@ static int nct7802_read_temp(struct nct7802_data *data, ...@@ -229,41 +229,34 @@ static int nct7802_read_temp(struct nct7802_data *data,
static int nct7802_read_fan(struct nct7802_data *data, u8 reg_fan) static int nct7802_read_fan(struct nct7802_data *data, u8 reg_fan)
{ {
unsigned int f1, f2; unsigned int regs[2] = {reg_fan, REG_FANCOUNT_LOW};
u8 f[2];
int ret; int ret;
mutex_lock(&data->access_lock); ret = regmap_multi_reg_read(data->regmap, regs, f, 2);
ret = regmap_read(data->regmap, reg_fan, &f1); if (ret)
if (ret < 0) return ret;
goto abort; ret = (f[0] << 5) | (f[1] >> 3);
ret = regmap_read(data->regmap, REG_FANCOUNT_LOW, &f2);
if (ret < 0)
goto abort;
ret = (f1 << 5) | (f2 >> 3);
/* convert fan count to rpm */ /* convert fan count to rpm */
if (ret == 0x1fff) /* maximum value, assume fan is stopped */ if (ret == 0x1fff) /* maximum value, assume fan is stopped */
ret = 0; ret = 0;
else if (ret) else if (ret)
ret = DIV_ROUND_CLOSEST(1350000U, ret); ret = DIV_ROUND_CLOSEST(1350000U, ret);
abort:
mutex_unlock(&data->access_lock);
return ret; return ret;
} }
static int nct7802_read_fan_min(struct nct7802_data *data, u8 reg_fan_low, static int nct7802_read_fan_min(struct nct7802_data *data, u8 reg_fan_low,
u8 reg_fan_high) u8 reg_fan_high)
{ {
unsigned int f1, f2; unsigned int regs[2] = {reg_fan_low, reg_fan_high};
u8 f[2];
int ret; int ret;
mutex_lock(&data->access_lock); ret = regmap_multi_reg_read(data->regmap, regs, f, 2);
ret = regmap_read(data->regmap, reg_fan_low, &f1);
if (ret < 0)
goto abort;
ret = regmap_read(data->regmap, reg_fan_high, &f2);
if (ret < 0) if (ret < 0)
goto abort; return ret;
ret = f1 | ((f2 & 0xf8) << 5);
ret = f[0] | ((f[1] & 0xf8) << 5);
/* convert fan count to rpm */ /* convert fan count to rpm */
if (ret == 0x1fff) /* maximum value, assume no limit */ if (ret == 0x1fff) /* maximum value, assume no limit */
ret = 0; ret = 0;
...@@ -271,8 +264,6 @@ static int nct7802_read_fan_min(struct nct7802_data *data, u8 reg_fan_low, ...@@ -271,8 +264,6 @@ static int nct7802_read_fan_min(struct nct7802_data *data, u8 reg_fan_low,
ret = DIV_ROUND_CLOSEST(1350000U, ret); ret = DIV_ROUND_CLOSEST(1350000U, ret);
else else
ret = 1350000U; ret = 1350000U;
abort:
mutex_unlock(&data->access_lock);
return ret; return ret;
} }
...@@ -302,33 +293,26 @@ static u8 nct7802_vmul[] = { 4, 2, 2, 2, 2 }; ...@@ -302,33 +293,26 @@ static u8 nct7802_vmul[] = { 4, 2, 2, 2, 2 };
static int nct7802_read_voltage(struct nct7802_data *data, int nr, int index) static int nct7802_read_voltage(struct nct7802_data *data, int nr, int index)
{ {
unsigned int v1, v2; u8 v[2];
int ret; int ret;
mutex_lock(&data->access_lock);
if (index == 0) { /* voltage */ if (index == 0) { /* voltage */
ret = regmap_read(data->regmap, REG_VOLTAGE[nr], &v1); unsigned int regs[2] = {REG_VOLTAGE[nr], REG_VOLTAGE_LOW};
if (ret < 0)
goto abort; ret = regmap_multi_reg_read(data->regmap, regs, v, 2);
ret = regmap_read(data->regmap, REG_VOLTAGE_LOW, &v2);
if (ret < 0) if (ret < 0)
goto abort; return ret;
ret = ((v1 << 2) | (v2 >> 6)) * nct7802_vmul[nr]; ret = ((v[0] << 2) | (v[1] >> 6)) * nct7802_vmul[nr];
} else { /* limit */ } else { /* limit */
int shift = 8 - REG_VOLTAGE_LIMIT_MSB_SHIFT[index - 1][nr]; int shift = 8 - REG_VOLTAGE_LIMIT_MSB_SHIFT[index - 1][nr];
unsigned int regs[2] = {REG_VOLTAGE_LIMIT_LSB[index - 1][nr],
REG_VOLTAGE_LIMIT_MSB[nr]};
ret = regmap_read(data->regmap, ret = regmap_multi_reg_read(data->regmap, regs, v, 2);
REG_VOLTAGE_LIMIT_LSB[index - 1][nr], &v1);
if (ret < 0)
goto abort;
ret = regmap_read(data->regmap, REG_VOLTAGE_LIMIT_MSB[nr],
&v2);
if (ret < 0) if (ret < 0)
goto abort; return ret;
ret = (v1 | ((v2 << shift) & 0x300)) * nct7802_vmul[nr]; ret = (v[0] | ((v[1] << shift) & 0x300)) * nct7802_vmul[nr];
} }
abort:
mutex_unlock(&data->access_lock);
return ret; return ret;
} }
...@@ -1145,17 +1129,14 @@ static int nct7802_configure_channels(struct device *dev, ...@@ -1145,17 +1129,14 @@ static int nct7802_configure_channels(struct device *dev,
{ {
/* Enable local temperature sensor by default */ /* Enable local temperature sensor by default */
u8 mode_mask = MODE_LTD_EN, mode_val = MODE_LTD_EN; u8 mode_mask = MODE_LTD_EN, mode_val = MODE_LTD_EN;
struct device_node *node;
int err; int err;
if (dev->of_node) { if (dev->of_node) {
for_each_child_of_node(dev->of_node, node) { for_each_child_of_node_scoped(dev->of_node, node) {
err = nct7802_get_channel_config(dev, node, &mode_mask, err = nct7802_get_channel_config(dev, node, &mode_mask,
&mode_val); &mode_val);
if (err) { if (err)
of_node_put(node);
return err; return err;
}
} }
} }
......
...@@ -927,7 +927,7 @@ static int npcm7xx_en_pwm_fan(struct device *dev, ...@@ -927,7 +927,7 @@ static int npcm7xx_en_pwm_fan(struct device *dev,
static int npcm7xx_pwm_fan_probe(struct platform_device *pdev) static int npcm7xx_pwm_fan_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *np, *child; struct device_node *np;
struct npcm7xx_pwm_fan_data *data; struct npcm7xx_pwm_fan_data *data;
struct resource *res; struct resource *res;
struct device *hwmon; struct device *hwmon;
...@@ -1004,11 +1004,10 @@ static int npcm7xx_pwm_fan_probe(struct platform_device *pdev) ...@@ -1004,11 +1004,10 @@ static int npcm7xx_pwm_fan_probe(struct platform_device *pdev)
} }
} }
for_each_child_of_node(np, child) { for_each_child_of_node_scoped(np, child) {
ret = npcm7xx_en_pwm_fan(dev, child, data); ret = npcm7xx_en_pwm_fan(dev, child, data);
if (ret) { if (ret) {
dev_err(dev, "enable pwm and fan failed\n"); dev_err(dev, "enable pwm and fan failed\n");
of_node_put(child);
return ret; return ret;
} }
} }
......
...@@ -62,6 +62,7 @@ static const struct platform_device_id ntc_thermistor_id[] = { ...@@ -62,6 +62,7 @@ static const struct platform_device_id ntc_thermistor_id[] = {
[NTC_SSG1404001221] = { "ssg1404_001221", TYPE_NCPXXWB473 }, [NTC_SSG1404001221] = { "ssg1404_001221", TYPE_NCPXXWB473 },
[NTC_LAST] = { }, [NTC_LAST] = { },
}; };
MODULE_DEVICE_TABLE(platform, ntc_thermistor_id);
/* /*
* A compensation table should be sorted by the values of .ohm * A compensation table should be sorted by the values of .ohm
......
This diff is collapsed.
...@@ -1315,7 +1315,7 @@ static void pc87360_init_device(struct platform_device *pdev, ...@@ -1315,7 +1315,7 @@ static void pc87360_init_device(struct platform_device *pdev,
(reg & 0xC0) | 0x11); (reg & 0xC0) | 0x11);
} }
nr = data->innr < 11 ? data->innr : 11; nr = min(data->innr, 11);
for (i = 0; i < nr; i++) { for (i = 0; i < nr; i++) {
reg = pc87360_read_value(data, LD_IN, i, reg = pc87360_read_value(data, LD_IN, i,
PC87365_REG_IN_STATUS); PC87365_REG_IN_STATUS);
......
This diff is collapsed.
...@@ -35,7 +35,7 @@ struct mpq7932_data { ...@@ -35,7 +35,7 @@ struct mpq7932_data {
}; };
#if IS_ENABLED(CONFIG_SENSORS_MPQ7932_REGULATOR) #if IS_ENABLED(CONFIG_SENSORS_MPQ7932_REGULATOR)
static struct regulator_desc mpq7932_regulators_desc[] = { static const struct regulator_desc mpq7932_regulators_desc[] = {
PMBUS_REGULATOR_STEP("buck", 0, MPQ7932_N_VOLTAGES, PMBUS_REGULATOR_STEP("buck", 0, MPQ7932_N_VOLTAGES,
MPQ7932_UV_STEP, MPQ7932_BUCK_UV_MIN), MPQ7932_UV_STEP, MPQ7932_BUCK_UV_MIN),
PMBUS_REGULATOR_STEP("buck", 1, MPQ7932_N_VOLTAGES, PMBUS_REGULATOR_STEP("buck", 1, MPQ7932_N_VOLTAGES,
......
...@@ -54,30 +54,6 @@ static int pli1209bc_read_word_data(struct i2c_client *client, int page, ...@@ -54,30 +54,6 @@ static int pli1209bc_read_word_data(struct i2c_client *client, int page,
} }
} }
static int pli1209bc_write_byte(struct i2c_client *client, int page, u8 reg)
{
int ret;
switch (reg) {
case PMBUS_CLEAR_FAULTS:
ret = pmbus_write_byte(client, page, reg);
/*
* PLI1209 takes 230 usec to execute the CLEAR_FAULTS command.
* During that time it's busy and NACKs all requests on the
* SMBUS interface. It also NACKs reads on PMBUS_STATUS_BYTE
* making it impossible to poll the BUSY flag.
*
* Just wait for not BUSY unconditionally.
*/
usleep_range(250, 300);
break;
default:
ret = -ENODATA;
break;
}
return ret;
}
#if IS_ENABLED(CONFIG_SENSORS_PLI1209BC_REGULATOR) #if IS_ENABLED(CONFIG_SENSORS_PLI1209BC_REGULATOR)
static const struct regulator_desc pli1209bc_reg_desc = { static const struct regulator_desc pli1209bc_reg_desc = {
.name = "vout2", .name = "vout2",
...@@ -127,7 +103,7 @@ static struct pmbus_driver_info pli1209bc_info = { ...@@ -127,7 +103,7 @@ static struct pmbus_driver_info pli1209bc_info = {
| PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP
| PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_STATUS_INPUT, | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_STATUS_INPUT,
.read_word_data = pli1209bc_read_word_data, .read_word_data = pli1209bc_read_word_data,
.write_byte = pli1209bc_write_byte, .write_delay = 250,
#if IS_ENABLED(CONFIG_SENSORS_PLI1209BC_REGULATOR) #if IS_ENABLED(CONFIG_SENSORS_PLI1209BC_REGULATOR)
.num_regulators = 1, .num_regulators = 1,
.reg_desc = &pli1209bc_reg_desc, .reg_desc = &pli1209bc_reg_desc,
......
...@@ -472,6 +472,16 @@ struct pmbus_driver_info { ...@@ -472,6 +472,16 @@ struct pmbus_driver_info {
/* custom attributes */ /* custom attributes */
const struct attribute_group **groups; const struct attribute_group **groups;
/*
* Some chips need a little delay between SMBus communication. When
* set, the generic PMBus helper functions will wait if necessary
* to meet this requirement. The access delay is honored after
* every SMBus operation. The write delay is only honored after
* SMBus write operations.
*/
int access_delay; /* in microseconds */
int write_delay; /* in microseconds */
}; };
/* Regulator ops */ /* Regulator ops */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -416,8 +416,7 @@ static int sch5636_probe(struct platform_device *pdev) ...@@ -416,8 +416,7 @@ static int sch5636_probe(struct platform_device *pdev)
id[i] = '\0'; id[i] = '\0';
if (strcmp(id, "THS")) { if (strcmp(id, "THS")) {
pr_err("Unknown Fujitsu id: %02x%02x%02x\n", pr_err("Unknown Fujitsu id: %3pE (%3ph)\n", id, id);
id[0], id[1], id[2]);
err = -ENODEV; err = -ENODEV;
goto error; goto error;
} }
......
...@@ -22,4 +22,3 @@ int sch56xx_read_virtual_reg12(u16 addr, u16 msb_reg, u16 lsn_reg, ...@@ -22,4 +22,3 @@ int sch56xx_read_virtual_reg12(u16 addr, u16 msb_reg, u16 lsn_reg,
void sch56xx_watchdog_register(struct device *parent, u16 addr, u32 revision, void sch56xx_watchdog_register(struct device *parent, u16 addr, u32 revision,
struct mutex *io_lock, int check_enabled); struct mutex *io_lock, int check_enabled);
void sch56xx_watchdog_unregister(struct sch56xx_watchdog_data *data);
This diff is collapsed.
...@@ -199,10 +199,7 @@ static ssize_t eic_read(struct sht21 *sht21) ...@@ -199,10 +199,7 @@ static ssize_t eic_read(struct sht21 *sht21)
eic[6] = rx[0]; eic[6] = rx[0];
eic[7] = rx[1]; eic[7] = rx[1];
ret = snprintf(sht21->eic, sizeof(sht21->eic), ret = snprintf(sht21->eic, sizeof(sht21->eic), "%8phN\n", eic);
"%02x%02x%02x%02x%02x%02x%02x%02x\n",
eic[0], eic[1], eic[2], eic[3],
eic[4], eic[5], eic[6], eic[7]);
out: out:
if (ret < 0) if (ret < 0)
sht21->eic[0] = 0; sht21->eic[0] = 0;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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