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:
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.
$ref: /schemas/types.yaml#/definitions/uint32-array
deprecated: true
minItems: 3
maxItems: 3
items:
enum: [0, 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:
"^adi,bypass-attenuator-in[0-4]$":
description: |
......@@ -81,6 +100,10 @@ patternProperties:
- smbalert#
- gpio
"^fan-[0-9]+$":
$ref: fan-common.yaml#
unevaluatedProperties: false
required:
- compatible
- reg
......@@ -89,17 +112,27 @@ additionalProperties: false
examples:
- |
#include <dt-bindings/pwm/pwm.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
hwmon@2e {
pwm: hwmon@2e {
compatible = "adi,adt7476";
reg = <0x2e>;
adi,bypass-attenuator-in0 = <1>;
adi,bypass-attenuator-in1 = <0>;
adi,pwm-active-state = <1 0 1>;
adi,pin10-function = "smbalert#";
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::
void hwmon_device_unregister(struct device *dev);
void devm_hwmon_device_unregister(struct device *dev);
char *hwmon_sanitize_name(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
remove function if the hardware monitoring device was registered with
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
names. Device names including invalid characters (whitespace, '*', or '-')
will be rejected. The 'name' parameter is mandatory.
......
......@@ -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_crit Critical high shunt voltage
in0_lcrit_alarm Shunt voltage critical low alarm
......
......@@ -206,6 +206,7 @@ Hardware Monitoring Kernel Drivers
sch5636
scpi-hwmon
sfctemp
sg2042-mcu
sht15
sht21
sht3x
......
......@@ -3,29 +3,29 @@ Kernel driver lm92
Supported chips:
* National Semiconductor LM92
* National Semiconductor / Texas Instruments LM92
Prefix: 'lm92'
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'
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'
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:
......@@ -36,13 +36,13 @@ Authors:
Description
-----------
This driver implements support for the National Semiconductor LM92
temperature sensor.
This driver implements support for the National Semiconductor / Texas
Instruments LM92 temperature sensor.
Each LM92 temperature sensor supports a single temperature sensor. There are
alarms for high, low, and critical thresholds. There's also an hysteresis to
control the thresholds for resetting alarms.
Support was added later for the LM76 and Maxim MAX6633/MAX6634/MAX6635,
which are mostly compatible. They have not all been tested, so you
may need to use the force parameter.
The driver also supports LM76 and Maxim MAX6633/MAX6634/MAX6635, which are
mostly compatible but do not have a vendor ID register and therefore must be
instantiated explicitly.
......@@ -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.
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:
Description:
------------
Handheld devices from One Netbook and Aya Neo provide fan readings and fan
control through their embedded controllers.
Handheld devices from OneNetbook, AOKZOE, AYANEO, And OrangePi provide fan
readings and fan control through their embedded controllers.
Currently only supports AMD boards from One X Player, AOK ZOE, and some Aya
Neo devices. One X Player Intel boards could be supported if we could figure
out the EC registers and values to write to since the EC layout and model is
different. Aya Neo devices preceding the AIR may not be supportable as the EC
model is different and do not appear to have manual control capabilities.
Currently supports OneXPlayer devices, AOKZOE, AYANEO, and OrangePi
handheld devices. AYANEO devices preceding the AIR and OneXPlayer devices
preceding the Mini A07 are not supportable as the EC model is different
and do not have manual control capabilities.
Some models have a toggle for changing the behaviour of the "Turbo/Silent"
button of the device. It will change the key event that it triggers with
a flip of the `tt_toggle` attribute. See below for boards that support this
function.
Some OneXPlayer and AOKZOE models have a toggle for changing the behaviour
of the "Turbo/Silent" button of the device. It will change the key event
that it triggers with a flip of the `tt_toggle` attribute. See below for
boards that support this function.
Supported devices
-----------------
Currently the driver supports the following handhelds:
- AOK ZOE A1
- AOK ZOE A1 PRO
- Aya Neo 2
- Aya Neo AIR
- Aya Neo AIR Plus (Mendocino)
- Aya Neo AIR Pro
- Aya Neo Geek
- AOKZOE A1
- AOKZOE A1 PRO
- AYANEO 2
- AYANEO 2S
- AYANEO AIR
- AYANEO AIR 1S
- 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 mini AMD
- 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:
- AOK ZOE A1
- AOK ZOE A1 PRO
- OneXPlayer 2
- OneXPlayer 2 Pro
- OneXPlayer mini AMD (only with updated alpha BIOS)
- OneXPlayer mini AMD PRO
- OneXPlayer OneXFly
- OneXPlayer X1 A
- OneXPlayer X1 i
- OneXPlayer X1 mini
Sysfs entries
-------------
......@@ -52,7 +70,7 @@ Sysfs entries
The following attributes are supported:
fan1_input
Read Only. Reads current fan RMP.
Read Only. Reads current fan RPM.
pwm1_enable
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
F: Documentation/hwmon/surface_fan.rst
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
M: Maximilian Luz <luzmaximilian@gmail.com>
L: platform-driver-x86@vger.kernel.org
......
......@@ -1511,9 +1511,10 @@ config SENSORS_LM90
config SENSORS_LM92
tristate "National Semiconductor LM92 and compatibles"
depends on I2C
select REGMAP_I2C
help
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
will be called lm92.
......@@ -1532,6 +1533,7 @@ config SENSORS_LM93
config SENSORS_LM95234
tristate "National Semiconductor LM95234 and compatibles"
depends on I2C
select REGMAP_I2C
help
If you say yes here you get support for the LM95233 and LM95234
temperature sensor chips.
......@@ -2066,6 +2068,17 @@ config SENSORS_SFCTEMP
This driver can also be built as a module. If so, the module
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
tristate "Surface Fan Driver"
depends on SURFACE_AGGREGATOR
......@@ -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.
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
tristate "Texas Instruments ADC128D818"
depends on I2C
......
......@@ -194,6 +194,7 @@ obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o
obj-$(CONFIG_SENSORS_SCH5627) += sch5627.o
obj-$(CONFIG_SENSORS_SCH5636) += sch5636.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_SHT15) += sht15.o
obj-$(CONFIG_SENSORS_SHT21) += sht21.o
......@@ -209,6 +210,7 @@ obj-$(CONFIG_SENSORS_SPARX5) += sparx5-temp.o
obj-$(CONFIG_SENSORS_SPD5118) += spd5118.o
obj-$(CONFIG_SENSORS_STTS751) += stts751.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_AMC6821) += amc6821.o
obj-$(CONFIG_SENSORS_TC74) += tc74.o
......
......@@ -728,30 +728,22 @@ static const int adt7470_freq_map[] = {
static int pwm1_freq_get(struct device *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 err;
mutex_lock(&data->lock);
err = regmap_read(data->regmap, ADT7470_REG_CFG, &cfg_reg_1);
if (err < 0)
goto out;
err = regmap_read(data->regmap, ADT7470_REG_CFG_2, &cfg_reg_2);
if (err < 0)
goto out;
mutex_unlock(&data->lock);
err = regmap_multi_reg_read(data->regmap, regs, cfg_reg, 2);
if (err)
return err;
index = (cfg_reg_2 & ADT7470_FREQ_MASK) >> ADT7470_FREQ_SHIFT;
if (!(cfg_reg_1 & ADT7470_CFG_LF))
index = (cfg_reg[1] & ADT7470_FREQ_MASK) >> ADT7470_FREQ_SHIFT;
if (!(cfg_reg[0] & ADT7470_CFG_LF))
index += 8;
if (index >= ARRAY_SIZE(adt7470_freq_map))
index = ARRAY_SIZE(adt7470_freq_map) - 1;
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)
......
......@@ -21,6 +21,8 @@
#include <linux/of.h>
#include <linux/util_macros.h>
#include <dt-bindings/pwm/pwm.h>
/* Indexes for the sysfs hooks */
enum adt_sysfs_id {
INPUT = 0,
......@@ -1662,6 +1664,130 @@ static int adt7475_set_pwm_polarity(struct i2c_client *client)
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)
{
enum chips chip;
......@@ -1774,6 +1900,10 @@ static int adt7475_probe(struct i2c_client *client)
if (ret && ret != -EINVAL)
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 */
switch (chip) {
case adt7475:
......
......@@ -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)
{
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_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);
ret = regmap_multi_reg_read(data->regmap, regs, regdata, 2);
if (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
......@@ -194,7 +188,7 @@ static int adt7x10_hyst_read(struct adt7x10_data *data, int index, long *val)
if (index == adt7x10_t_alarm_low)
hyst = -hyst;
*val = ADT7X10_REG_TO_TEMP(data, temp) - hyst;
*val = ADT7X10_REG_TO_TEMP(data, regdata[1]) - hyst;
return 0;
}
......
......@@ -136,29 +136,25 @@ struct amc6821_data {
*/
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;
err = regmap_read(regmap, AMC6821_REG_DCY_LOW_TEMP, &pwm);
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);
err = regmap_multi_reg_read(regmap, regs, regvals, 3);
if (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 */
regval = 32 >> FIELD_GET(AMC6821_TEMP_SLOPE_MASK, regval);
if (regval)
temps[2] = temps[1] + DIV_ROUND_CLOSEST(255 - pwm, regval);
slope = 32 >> FIELD_GET(AMC6821_TEMP_SLOPE_MASK, regvals[2]);
if (slope)
temps[2] = temps[1] + DIV_ROUND_CLOSEST(255 - regvals[0], slope);
else
temps[2] = 255;
......
......@@ -456,7 +456,6 @@ static int aspeed_pwm_tach_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev, *hwmon;
int ret;
struct device_node *child;
struct aspeed_pwm_tach_data *priv;
struct pwm_chip *chip;
......@@ -498,10 +497,9 @@ static int aspeed_pwm_tach_probe(struct platform_device *pdev)
if (ret)
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);
if (ret) {
of_node_put(child);
dev_warn(dev, "Failed to create fan %d", ret);
return 0;
}
......
......@@ -907,7 +907,7 @@ static void aspeed_pwm_tacho_remove(void *data)
static int aspeed_pwm_tacho_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np, *child;
struct device_node *np;
struct aspeed_pwm_tacho_data *priv;
void __iomem *regs;
struct device *hwmon;
......@@ -951,12 +951,10 @@ static int aspeed_pwm_tacho_probe(struct platform_device *pdev)
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);
if (ret) {
of_node_put(child);
if (ret)
return ret;
}
}
priv->groups[0] = &pwm_dev_group;
......
......@@ -740,37 +740,26 @@ static int cc2_probe(struct i2c_client *client)
data->client = client;
data->regulator = devm_regulator_get_exclusive(dev, "vdd");
if (IS_ERR(data->regulator)) {
dev_err_probe(dev, PTR_ERR(data->regulator),
"Failed to get regulator\n");
return PTR_ERR(data->regulator);
}
if (IS_ERR(data->regulator))
return dev_err_probe(dev, PTR_ERR(data->regulator),
"Failed to get regulator\n");
ret = cc2_request_ready_irq(data, dev);
if (ret) {
dev_err_probe(dev, ret, "Failed to request ready irq\n");
return ret;
}
if (ret)
return dev_err_probe(dev, ret, "Failed to request ready irq\n");
ret = cc2_request_alarm_irqs(data, dev);
if (ret) {
dev_err_probe(dev, ret, "Failed to request alarm irqs\n");
goto disable;
}
if (ret)
return dev_err_probe(dev, ret, "Failed to request alarm irqs\n");
data->hwmon = devm_hwmon_device_register_with_info(dev, client->name,
data, &cc2_chip_info,
NULL);
if (IS_ERR(data->hwmon)) {
dev_err_probe(dev, PTR_ERR(data->hwmon),
"Failed to register hwmon device\n");
ret = PTR_ERR(data->hwmon);
}
disable:
cc2_disable(data);
if (IS_ERR(data->hwmon))
return dev_err_probe(dev, PTR_ERR(data->hwmon),
"Failed to register hwmon device\n");
return ret;
return 0;
}
static void cc2_remove(struct i2c_client *client)
......
......@@ -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],
},
{
.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",
.matches = {
......
......@@ -400,6 +400,7 @@ static const struct of_device_id gsc_hwmon_of_match[] = {
{ .compatible = "gw,gsc-adc", },
{}
};
MODULE_DEVICE_TABLE(of, gsc_hwmon_of_match);
static struct platform_driver gsc_hwmon_driver = {
.driver = {
......
......@@ -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);
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)
{
char *name, *p;
......
This diff is collapsed.
......@@ -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)
{
const struct device_node *np = dev->of_node;
struct device_node *child;
int ret;
/* Compatible with non-DT platforms */
......@@ -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");
for_each_child_of_node(np, child) {
for_each_child_of_node_scoped(np, child) {
ret = ina3221_probe_child_from_dt(dev, child, ina);
if (ret) {
of_node_put(child);
if (ret)
return ret;
}
}
return 0;
......
......@@ -438,16 +438,21 @@ static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
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) == 0x70)) {
data->read_htcreg = read_htcreg_nb_f15;
data->read_tempreg = read_tempreg_nb_f15;
} else if (boot_cpu_data.x86 == 0x17 || boot_cpu_data.x86 == 0x18) {
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;
}
if (boot_cpu_data.x86 == 0x17 || boot_cpu_data.x86 == 0x18) {
switch (boot_cpu_data.x86_model) {
case 0x1: /* Zen */
case 0x8: /* Zen+ */
......@@ -469,10 +474,6 @@ static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
break;
}
} 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) {
case 0x0 ... 0x1: /* Zen3 SP3/TR */
case 0x8: /* Zen3 TR Chagall */
......@@ -496,13 +497,6 @@ static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
k10temp_get_ccd_support(data, 12);
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++) {
......
......@@ -2674,19 +2674,16 @@ static int lm90_parse_dt_channel_info(struct i2c_client *client,
struct lm90_data *data)
{
int err;
struct device_node *child;
struct device *dev = &client->dev;
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"))
continue;
err = lm90_probe_channel_from_dt(client, child, data);
if (err) {
of_node_put(child);
if (err)
return err;
}
}
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,
{
struct lm95245_data *data = dev_get_drvdata(dev);
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) {
case hwmon_temp_input:
regl = channel ? LM95245_REG_R_REMOTE_TEMPL_S :
LM95245_REG_R_LOCAL_TEMPL_S;
regh = channel ? LM95245_REG_R_REMOTE_TEMPH_S :
LM95245_REG_R_LOCAL_TEMPH_S;
ret = regmap_read(regmap, regl, &regvall);
if (ret < 0)
return ret;
ret = regmap_read(regmap, regh, &regvalh);
regs[0] = channel ? LM95245_REG_R_REMOTE_TEMPL_S :
LM95245_REG_R_LOCAL_TEMPL_S;
regs[1] = channel ? LM95245_REG_R_REMOTE_TEMPH_S :
LM95245_REG_R_LOCAL_TEMPH_S;
ret = regmap_multi_reg_read(regmap, regs, regvals, 2);
if (ret < 0)
return ret;
/*
......@@ -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
* or if reported temperature is below signed limit.
*/
if (!channel || (regvalh & 0x80) || regvalh < 0x7f) {
*val = temp_from_reg_signed(regvalh, regvall);
if (!channel || (regvals[1] & 0x80) || regvals[1] < 0x7f) {
*val = temp_from_reg_signed(regvals[1], regvals[0]);
return 0;
}
ret = regmap_read(regmap, LM95245_REG_R_REMOTE_TEMPL_U,
&regvall);
if (ret < 0)
return ret;
ret = regmap_read(regmap, LM95245_REG_R_REMOTE_TEMPH_U,
&regvalh);
if (ret < 0)
ret = regmap_bulk_read(regmap, LM95245_REG_R_REMOTE_TEMPH_U, regvals, 2);
if (ret)
return ret;
*val = temp_from_reg_unsigned(regvalh, regvall);
*val = temp_from_reg_unsigned(regvals[0], regvals[1]);
return 0;
case hwmon_temp_max:
ret = regmap_read(regmap, LM95245_REG_RW_REMOTE_OS_LIMIT,
&regvalh);
&regval);
if (ret < 0)
return ret;
*val = regvalh * 1000;
*val = regval * 1000;
return 0;
case hwmon_temp_crit:
regh = channel ? LM95245_REG_RW_REMOTE_TCRIT_LIMIT :
LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT;
ret = regmap_read(regmap, regh, &regvalh);
regs[0] = channel ? LM95245_REG_RW_REMOTE_TCRIT_LIMIT :
LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT;
ret = regmap_read(regmap, regs[0], &regval);
if (ret < 0)
return ret;
*val = regvalh * 1000;
*val = regval * 1000;
return 0;
case hwmon_temp_max_hyst:
ret = regmap_read(regmap, LM95245_REG_RW_REMOTE_OS_LIMIT,
&regvalh);
regs[0] = LM95245_REG_RW_REMOTE_OS_LIMIT;
regs[1] = LM95245_REG_RW_COMMON_HYSTERESIS;
ret = regmap_multi_reg_read(regmap, regs, regvals, 2);
if (ret < 0)
return ret;
ret = regmap_read(regmap, LM95245_REG_RW_COMMON_HYSTERESIS,
&regvall);
if (ret < 0)
return ret;
*val = (regvalh - regvall) * 1000;
*val = (regvals[0] - regvals[1]) * 1000;
return 0;
case hwmon_temp_crit_hyst:
regh = channel ? LM95245_REG_RW_REMOTE_TCRIT_LIMIT :
LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT;
ret = regmap_read(regmap, regh, &regvalh);
if (ret < 0)
return ret;
ret = regmap_read(regmap, LM95245_REG_RW_COMMON_HYSTERESIS,
&regvall);
regs[0] = channel ? LM95245_REG_RW_REMOTE_TCRIT_LIMIT :
LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT;
regs[1] = LM95245_REG_RW_COMMON_HYSTERESIS;
ret = regmap_multi_reg_read(regmap, regs, regvals, 2);
if (ret < 0)
return ret;
*val = (regvalh - regvall) * 1000;
*val = (regvals[0] - regvals[1]) * 1000;
return 0;
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)
return ret;
*val = (regvalh & CFG2_REMOTE_TT) ? 1 : 2;
*val = (regval & CFG2_REMOTE_TT) ? 1 : 2;
return 0;
case hwmon_temp_offset:
ret = regmap_read(regmap, LM95245_REG_RW_REMOTE_OFFL,
&regvall);
if (ret < 0)
return ret;
ret = regmap_read(regmap, LM95245_REG_RW_REMOTE_OFFH,
&regvalh);
ret = regmap_bulk_read(regmap, LM95245_REG_RW_REMOTE_OFFH, regvals, 2);
if (ret < 0)
return ret;
*val = temp_from_reg_signed(regvalh, regvall);
*val = temp_from_reg_signed(regvals[0], regvals[1]);
return 0;
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)
return ret;
*val = !!(regvalh & STATUS1_ROS);
*val = !!(regval & STATUS1_ROS);
return 0;
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)
return ret;
*val = !!(regvalh & (channel ? STATUS1_RTCRIT : STATUS1_LOC));
*val = !!(regval & (channel ? STATUS1_RTCRIT : STATUS1_LOC));
return 0;
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)
return ret;
*val = !!(regvalh & STATUS1_DIODE_FAULT);
*val = !!(regval & STATUS1_DIODE_FAULT);
return 0;
default:
return -EOPNOTSUPP;
......@@ -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 regmap *regmap = data->regmap;
unsigned int regval;
u8 regvals[2];
int ret, reg;
switch (attr) {
......@@ -311,16 +297,10 @@ static int lm95245_write_temp(struct device *dev, u32 attr, int channel,
case hwmon_temp_offset:
val = clamp_val(val, -128000, 127875);
val = val * 256 / 1000;
mutex_lock(&data->update_lock);
ret = regmap_write(regmap, LM95245_REG_RW_REMOTE_OFFL,
val & 0xe0);
if (ret < 0) {
mutex_unlock(&data->update_lock);
return ret;
}
ret = regmap_write(regmap, LM95245_REG_RW_REMOTE_OFFH,
(val >> 8) & 0xff);
mutex_unlock(&data->update_lock);
regvals[0] = val >> 8;
regvals[1] = val & 0xe0;
ret = regmap_bulk_write(regmap, LM95245_REG_RW_REMOTE_OFFH, regvals, 2);
return ret;
case hwmon_temp_type:
if (val != 1 && val != 2)
......
......@@ -11,7 +11,8 @@
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/mod_devicetable.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include "ltc2947.h"
......@@ -1034,9 +1035,8 @@ static int ltc2947_setup(struct ltc2947_data *st)
/* 19.89E-6 * 10E9 */
st->lsb_energy = 19890;
}
ret = of_property_read_u32_array(st->dev->of_node,
"adi,accumulator-ctl-pol", accum,
ARRAY_SIZE(accum));
ret = device_property_read_u32_array(st->dev, "adi,accumulator-ctl-pol",
accum, ARRAY_SIZE(accum));
if (!ret) {
u32 accum_reg = LTC2947_ACCUM_POL_1(accum[0]) |
LTC2947_ACCUM_POL_2(accum[1]);
......@@ -1045,9 +1045,9 @@ static int ltc2947_setup(struct ltc2947_data *st)
if (ret)
return ret;
}
ret = of_property_read_u32(st->dev->of_node,
"adi,accumulation-deadband-microamp",
&deadband);
ret = device_property_read_u32(st->dev,
"adi,accumulation-deadband-microamp",
&deadband);
if (!ret) {
/* the LSB is the same as the current, so 3mA */
ret = regmap_write(st->map, LTC2947_REG_ACCUM_DEADBAND,
......@@ -1056,7 +1056,7 @@ static int ltc2947_setup(struct ltc2947_data *st)
return ret;
}
/* 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) {
/* setup GPIO as output */
u32 gpio_ctl = LTC2947_GPIO_EN(1) | LTC2947_GPIO_FAN_EN(1) |
......@@ -1067,8 +1067,8 @@ static int ltc2947_setup(struct ltc2947_data *st)
if (ret)
return ret;
}
ret = of_property_read_u32_array(st->dev->of_node, "adi,gpio-in-accum",
accum, ARRAY_SIZE(accum));
ret = device_property_read_u32_array(st->dev, "adi,gpio-in-accum",
accum, ARRAY_SIZE(accum));
if (!ret) {
/*
* Setup the accum options. The gpioctl is already defined as
......
......@@ -854,33 +854,24 @@ static const struct regmap_config ltc2992_regmap_config = {
static int ltc2992_parse_dt(struct ltc2992_state *st)
{
struct fwnode_handle *fwnode;
struct fwnode_handle *child;
u32 addr;
u32 val;
int ret;
fwnode = dev_fwnode(&st->client->dev);
fwnode_for_each_available_child_node(fwnode, child) {
device_for_each_child_node_scoped(&st->client->dev, child) {
ret = fwnode_property_read_u32(child, "reg", &addr);
if (ret < 0) {
fwnode_handle_put(child);
if (ret < 0)
return ret;
}
if (addr > 1) {
fwnode_handle_put(child);
if (addr > 1)
return -EINVAL;
}
ret = fwnode_property_read_u32(child, "shunt-resistor-micro-ohms", &val);
if (!ret) {
if (!val) {
fwnode_handle_put(child);
if (!val)
return dev_err_probe(&st->client->dev, -EINVAL,
"shunt resistor value cannot be zero\n");
}
st->r_sense_uohm[addr] = val;
}
}
......
......@@ -79,7 +79,7 @@ static const bool max16065_have_current[] = {
};
struct max16065_data {
enum chips type;
enum chips chip;
struct i2c_client *client;
const struct attribute_group *groups[4];
struct mutex update_lock;
......@@ -114,9 +114,10 @@ static inline int LIMIT_TO_MV(int limit, int range)
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)
......@@ -161,10 +162,17 @@ static struct max16065_data *max16065_update_device(struct device *dev)
MAX16065_CURR_SENSE);
}
for (i = 0; i < DIV_ROUND_UP(data->num_adc, 8); i++)
for (i = 0; i < 2; i++)
data->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->valid = true;
}
......@@ -513,6 +521,7 @@ static int max16065_probe(struct i2c_client *client)
if (unlikely(!data))
return -ENOMEM;
data->chip = chip;
data->client = client;
mutex_init(&data->update_lock);
......
This diff is collapsed.
This diff is collapsed.
......@@ -88,25 +88,16 @@ struct max6639_data {
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);
unsigned int val;
u8 regvals[2];
int res;
/*
* 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);
res = regmap_multi_reg_read(data->regmap, regs, regvals, 2);
if (res < 0)
return res;
*temp |= val << 3;
*temp *= 125;
*temp = ((regvals[0] >> 5) | (regvals[1] << 3)) * 125;
return 0;
}
......@@ -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,
long *pwm_val)
{
u32 regs[2] = { MAX6639_REG_FAN_CONFIG3(channel), MAX6639_REG_GCONFIG };
struct max6639_data *data = dev_get_drvdata(dev);
unsigned int val;
u8 regvals[2];
int res;
u8 i;
......@@ -303,26 +296,13 @@ static int max6639_read_pwm(struct device *dev, u32 attr, int channel,
*pwm_val = val * 255 / 120;
return 0;
case hwmon_pwm_freq:
mutex_lock(&data->update_lock);
res = regmap_read(data->regmap, MAX6639_REG_FAN_CONFIG3(channel), &val);
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);
res = regmap_multi_reg_read(data->regmap, regs, regvals, 2);
if (res < 0)
return res;
}
if (val & MAX6639_GCONFIG_PWM_FREQ_HI)
i = regvals[0] & MAX6639_FAN_CONFIG3_FREQ_MASK;
if (regvals[1] & MAX6639_GCONFIG_PWM_FREQ_HI)
i |= 0x4;
i &= 0x7;
*pwm_val = freq_table[i];
mutex_unlock(&data->update_lock);
return 0;
default:
return -EOPNOTSUPP;
......
This diff is collapsed.
......@@ -1269,6 +1269,7 @@ static const char * const asus_msi_boards[] = {
"EX-B760M-V5 D4",
"EX-H510M-V3",
"EX-H610M-V3 D4",
"G15CF",
"PRIME A620M-A",
"PRIME B560-PLUS",
"PRIME B560-PLUS AC-HES",
......
......@@ -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)
{
unsigned int f1, f2;
unsigned int regs[2] = {reg_fan, REG_FANCOUNT_LOW};
u8 f[2];
int ret;
mutex_lock(&data->access_lock);
ret = regmap_read(data->regmap, reg_fan, &f1);
if (ret < 0)
goto abort;
ret = regmap_read(data->regmap, REG_FANCOUNT_LOW, &f2);
if (ret < 0)
goto abort;
ret = (f1 << 5) | (f2 >> 3);
ret = regmap_multi_reg_read(data->regmap, regs, f, 2);
if (ret)
return ret;
ret = (f[0] << 5) | (f[1] >> 3);
/* convert fan count to rpm */
if (ret == 0x1fff) /* maximum value, assume fan is stopped */
ret = 0;
else if (ret)
ret = DIV_ROUND_CLOSEST(1350000U, ret);
abort:
mutex_unlock(&data->access_lock);
return ret;
}
static int nct7802_read_fan_min(struct nct7802_data *data, u8 reg_fan_low,
u8 reg_fan_high)
{
unsigned int f1, f2;
unsigned int regs[2] = {reg_fan_low, reg_fan_high};
u8 f[2];
int ret;
mutex_lock(&data->access_lock);
ret = regmap_read(data->regmap, reg_fan_low, &f1);
if (ret < 0)
goto abort;
ret = regmap_read(data->regmap, reg_fan_high, &f2);
ret = regmap_multi_reg_read(data->regmap, regs, f, 2);
if (ret < 0)
goto abort;
ret = f1 | ((f2 & 0xf8) << 5);
return ret;
ret = f[0] | ((f[1] & 0xf8) << 5);
/* convert fan count to rpm */
if (ret == 0x1fff) /* maximum value, assume no limit */
ret = 0;
......@@ -271,8 +264,6 @@ static int nct7802_read_fan_min(struct nct7802_data *data, u8 reg_fan_low,
ret = DIV_ROUND_CLOSEST(1350000U, ret);
else
ret = 1350000U;
abort:
mutex_unlock(&data->access_lock);
return ret;
}
......@@ -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)
{
unsigned int v1, v2;
u8 v[2];
int ret;
mutex_lock(&data->access_lock);
if (index == 0) { /* voltage */
ret = regmap_read(data->regmap, REG_VOLTAGE[nr], &v1);
if (ret < 0)
goto abort;
ret = regmap_read(data->regmap, REG_VOLTAGE_LOW, &v2);
unsigned int regs[2] = {REG_VOLTAGE[nr], REG_VOLTAGE_LOW};
ret = regmap_multi_reg_read(data->regmap, regs, v, 2);
if (ret < 0)
goto abort;
ret = ((v1 << 2) | (v2 >> 6)) * nct7802_vmul[nr];
return ret;
ret = ((v[0] << 2) | (v[1] >> 6)) * nct7802_vmul[nr];
} else { /* limit */
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,
REG_VOLTAGE_LIMIT_LSB[index - 1][nr], &v1);
if (ret < 0)
goto abort;
ret = regmap_read(data->regmap, REG_VOLTAGE_LIMIT_MSB[nr],
&v2);
ret = regmap_multi_reg_read(data->regmap, regs, v, 2);
if (ret < 0)
goto abort;
ret = (v1 | ((v2 << shift) & 0x300)) * nct7802_vmul[nr];
return ret;
ret = (v[0] | ((v[1] << shift) & 0x300)) * nct7802_vmul[nr];
}
abort:
mutex_unlock(&data->access_lock);
return ret;
}
......@@ -1145,17 +1129,14 @@ static int nct7802_configure_channels(struct device *dev,
{
/* Enable local temperature sensor by default */
u8 mode_mask = MODE_LTD_EN, mode_val = MODE_LTD_EN;
struct device_node *node;
int err;
if (dev->of_node) {
for_each_child_of_node(dev->of_node, node) {
for_each_child_of_node_scoped(dev->of_node, node) {
err = nct7802_get_channel_config(dev, node, &mode_mask,
&mode_val);
if (err) {
of_node_put(node);
if (err)
return err;
}
}
}
......
......@@ -927,7 +927,7 @@ static int npcm7xx_en_pwm_fan(struct device *dev,
static int npcm7xx_pwm_fan_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np, *child;
struct device_node *np;
struct npcm7xx_pwm_fan_data *data;
struct resource *res;
struct device *hwmon;
......@@ -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);
if (ret) {
dev_err(dev, "enable pwm and fan failed\n");
of_node_put(child);
return ret;
}
}
......
......@@ -62,6 +62,7 @@ static const struct platform_device_id ntc_thermistor_id[] = {
[NTC_SSG1404001221] = { "ssg1404_001221", TYPE_NCPXXWB473 },
[NTC_LAST] = { },
};
MODULE_DEVICE_TABLE(platform, ntc_thermistor_id);
/*
* 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,
(reg & 0xC0) | 0x11);
}
nr = data->innr < 11 ? data->innr : 11;
nr = min(data->innr, 11);
for (i = 0; i < nr; i++) {
reg = pc87360_read_value(data, LD_IN, i,
PC87365_REG_IN_STATUS);
......
This diff is collapsed.
......@@ -35,7 +35,7 @@ struct mpq7932_data {
};
#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,
MPQ7932_UV_STEP, MPQ7932_BUCK_UV_MIN),
PMBUS_REGULATOR_STEP("buck", 1, MPQ7932_N_VOLTAGES,
......
......@@ -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)
static const struct regulator_desc pli1209bc_reg_desc = {
.name = "vout2",
......@@ -127,7 +103,7 @@ static struct pmbus_driver_info pli1209bc_info = {
| PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP
| PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_STATUS_INPUT,
.read_word_data = pli1209bc_read_word_data,
.write_byte = pli1209bc_write_byte,
.write_delay = 250,
#if IS_ENABLED(CONFIG_SENSORS_PLI1209BC_REGULATOR)
.num_regulators = 1,
.reg_desc = &pli1209bc_reg_desc,
......
......@@ -472,6 +472,16 @@ struct pmbus_driver_info {
/* custom attributes */
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 */
......
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)
id[i] = '\0';
if (strcmp(id, "THS")) {
pr_err("Unknown Fujitsu id: %02x%02x%02x\n",
id[0], id[1], id[2]);
pr_err("Unknown Fujitsu id: %3pE (%3ph)\n", id, id);
err = -ENODEV;
goto error;
}
......
......@@ -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,
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)
eic[6] = rx[0];
eic[7] = rx[1];
ret = snprintf(sht21->eic, sizeof(sht21->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]);
ret = snprintf(sht21->eic, sizeof(sht21->eic), "%8phN\n", eic);
out:
if (ret < 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