aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2025-07-31 13:34:06 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2025-07-31 13:34:06 -0700
commitbe413ec746afc951c79d5907cf62ab6757330bdb (patch)
treecbb33b708b767c3c7f769bf122faad495804bfb4
parentMerge tag 'pwm/for-6.17-rc1-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/ukleinek/linux (diff)
parentdt-bindings: hwmon: Replace bouncing Alexandru Tachici emails (diff)
downloadwireguard-linux-be413ec746afc951c79d5907cf62ab6757330bdb.tar.xz
wireguard-linux-be413ec746afc951c79d5907cf62ab6757330bdb.zip
Merge tag 'hwmon-for-v6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging
Pull hwmon updates from Guenter Roeck: "Updated chip support in existing drivers: - ina238: Support for INA228 - pmbus/tps53679: Support for TPS53685 - pmbus/adp1050: Support for adp1051, adp1055 and ltp8800 - corsair-psu: Support for HX1200i Series 2025 - pmbus/isl68137: Support for RAA229621 - asus-ec-sensors: Support for ProArt X870E-CREATOR WIFI and Other notable changes: - adt7475: Support for #pwm-cells = <3> - amc6821: Cooling device support - emc2305: Support for PWM frequency, polarity and output - Add missing compatible entries to various devicetree bindings And various other minor fixes and improvements" * tag 'hwmon-for-v6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (34 commits) dt-bindings: hwmon: Replace bouncing Alexandru Tachici emails hwmon: (ina238) Add support for INA228 dt-bindings: Add INA228 to ina2xx devicetree bindings hwmon: (ina238) Fix inconsistent whitespace dt-bindings: hwmon: adt7475: Allow and recommend #pwm-cells = <3> hwmon: (adt7475) Implement support for #pwm-cells = <3> hwmon: (pmbus/tps53679) Add support for TPS53685 dt-bindings: trivial: Add tps53685 support hwmon: (pmbus/adp1050) Add regulator support for ltp8800 hwmon: (pmbus/adp1050) Add support for adp1051, adp1055 and ltp8800 dt-bindings: hwmon: pmbus/adp1050: Add adp1051, adp1055 and ltp8800 hwmon: (max31827) use sysfs_emit() in temp1_resolution_show() hwmon: (ltc4282) convert from round_rate() to determine_rate() hwmon: (corsair-psu) add support for HX1200i Series 2025 dt-bindings: hwmon: pmbus: ti,ucd90320: Add missing compatibles dt-bindings: hwmon: maxim,max20730: Add maxim,max20710 compatible dt-bindings: hwmon: lltc,ltc2978: Add lltc,ltc713 compatible dt-bindings: hwmon: ti,lm87: Add adi,adm1024 compatible dt-bindings: hwmon: national,lm90: Add missing Dallas max6654 and onsemi nct72, nct214, and nct218 hwmon: (w83627ehf) make the read-only arrays 'bit' static const ...
-rw-r--r--Documentation/devicetree/bindings/hwmon/adi,adm1266.yaml2
-rw-r--r--Documentation/devicetree/bindings/hwmon/adi,ltc2992.yaml2
-rw-r--r--Documentation/devicetree/bindings/hwmon/adt7475.yaml15
-rw-r--r--Documentation/devicetree/bindings/hwmon/lltc,ltc2978.yaml2
-rw-r--r--Documentation/devicetree/bindings/hwmon/maxim,max20730.yaml1
-rw-r--r--Documentation/devicetree/bindings/hwmon/national,lm90.yaml8
-rw-r--r--Documentation/devicetree/bindings/hwmon/pmbus/adi,adp1050.yaml15
-rw-r--r--Documentation/devicetree/bindings/hwmon/pmbus/isil,isl68137.yaml1
-rw-r--r--Documentation/devicetree/bindings/hwmon/pmbus/ti,ucd90320.yaml6
-rw-r--r--Documentation/devicetree/bindings/hwmon/ti,amc6821.yaml6
-rw-r--r--Documentation/devicetree/bindings/hwmon/ti,ina2xx.yaml2
-rw-r--r--Documentation/devicetree/bindings/hwmon/ti,lm87.yaml4
-rw-r--r--Documentation/devicetree/bindings/trivial-devices.yaml2
-rw-r--r--Documentation/hwmon/adp1050.rst71
-rw-r--r--Documentation/hwmon/asus_ec_sensors.rst2
-rw-r--r--Documentation/hwmon/corsair-psu.rst2
-rw-r--r--Documentation/hwmon/tps53679.rst8
-rw-r--r--drivers/hwmon/adt7475.c20
-rw-r--r--drivers/hwmon/amc6821.c127
-rw-r--r--drivers/hwmon/asus-ec-sensors.c60
-rw-r--r--drivers/hwmon/corsair-psu.c1
-rw-r--r--drivers/hwmon/emc2305.c181
-rw-r--r--drivers/hwmon/gsc-hwmon.c4
-rw-r--r--drivers/hwmon/ibmaem.c27
-rw-r--r--drivers/hwmon/ina238.c134
-rw-r--r--drivers/hwmon/ltc4282.c16
-rw-r--r--drivers/hwmon/max31827.c2
-rw-r--r--drivers/hwmon/pmbus/Kconfig9
-rw-r--r--drivers/hwmon/pmbus/adp1050.c72
-rw-r--r--drivers/hwmon/pmbus/isl68137.c3
-rw-r--r--drivers/hwmon/pmbus/tps53679.c37
-rw-r--r--drivers/hwmon/w83627ehf.c9
-rw-r--r--include/linux/platform_data/emc2305.h6
33 files changed, 743 insertions, 114 deletions
diff --git a/Documentation/devicetree/bindings/hwmon/adi,adm1266.yaml b/Documentation/devicetree/bindings/hwmon/adi,adm1266.yaml
index 4f8e11bd5142..fe87a592de45 100644
--- a/Documentation/devicetree/bindings/hwmon/adi,adm1266.yaml
+++ b/Documentation/devicetree/bindings/hwmon/adi,adm1266.yaml
@@ -8,7 +8,7 @@ title: Analog Devices ADM1266 Cascadable Super Sequencer with Margin
Control and Fault Recording
maintainers:
- - Alexandru Tachici <alexandru.tachici@analog.com>
+ - Cedric Encarnacion <cedricjustine.encarnacion@analog.com>
description: |
Analog Devices ADM1266 Cascadable Super Sequencer with Margin
diff --git a/Documentation/devicetree/bindings/hwmon/adi,ltc2992.yaml b/Documentation/devicetree/bindings/hwmon/adi,ltc2992.yaml
index 0ad12d245656..38a8f3a14c02 100644
--- a/Documentation/devicetree/bindings/hwmon/adi,ltc2992.yaml
+++ b/Documentation/devicetree/bindings/hwmon/adi,ltc2992.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Linear Technology 2992 Power Monitor
maintainers:
- - Alexandru Tachici <alexandru.tachici@analog.com>
+ - Cedric Encarnacion <cedricjustine.encarnacion@analog.com>
description: |
Linear Technology 2992 Dual Wide Range Power Monitor
diff --git a/Documentation/devicetree/bindings/hwmon/adt7475.yaml b/Documentation/devicetree/bindings/hwmon/adt7475.yaml
index 79e8d62fa3b3..43e9fe225870 100644
--- a/Documentation/devicetree/bindings/hwmon/adt7475.yaml
+++ b/Documentation/devicetree/bindings/hwmon/adt7475.yaml
@@ -53,7 +53,10 @@ properties:
default: 1
"#pwm-cells":
- const: 4
+ oneOf:
+ - const: 3
+ - const: 4
+ deprecated: true
description: |
Number of cells in a PWM specifier.
- 0: The PWM channel
@@ -68,7 +71,7 @@ properties:
- 11363636 (88 Hz)
- 44444 (22 kHz)
- 2: PWM flags 0 or PWM_POLARITY_INVERTED
- - 3: The default PWM duty cycle in nanoseconds
+ - 3: The default PWM duty cycle in nanoseconds, defaults to period.
patternProperties:
"^adi,bypass-attenuator-in[0-4]$":
@@ -124,15 +127,15 @@ examples:
adi,bypass-attenuator-in1 = <0>;
adi,pin10-function = "smbalert#";
adi,pin14-function = "tach4";
- #pwm-cells = <4>;
+ #pwm-cells = <3>;
- /* PWMs at 22.5 kHz frequency, 50% duty*/
+ /* PWMs at 22.5 kHz frequency */
fan-0 {
- pwms = <&pwm 0 44444 0 22222>;
+ pwms = <&pwm 0 44444 0>;
};
fan-1 {
- pwms = <&pwm 2 44444 0 22222>;
+ pwms = <&pwm 2 44444 0>;
};
};
};
diff --git a/Documentation/devicetree/bindings/hwmon/lltc,ltc2978.yaml b/Documentation/devicetree/bindings/hwmon/lltc,ltc2978.yaml
index aa801ef1640b..ea8b1553a3e9 100644
--- a/Documentation/devicetree/bindings/hwmon/lltc,ltc2978.yaml
+++ b/Documentation/devicetree/bindings/hwmon/lltc,ltc2978.yaml
@@ -28,6 +28,7 @@ properties:
- lltc,ltc3886
- lltc,ltc3887
- lltc,ltc3889
+ - lltc,ltc7132
- lltc,ltc7841
- lltc,ltc7880
- lltc,ltm2987
@@ -55,6 +56,7 @@ properties:
* ltc2977, ltc2979, ltc2980, ltm2987 : vout0 - vout7
* ltc2978 : vout0 - vout7
* ltc3880, ltc3882, ltc3884, ltc3886, ltc3887, ltc3889 : vout0 - vout1
+ * ltc7132 : vout0 - vout1
* ltc7841 : vout0
* ltc7880 : vout0 - vout1
* ltc3883 : vout0
diff --git a/Documentation/devicetree/bindings/hwmon/maxim,max20730.yaml b/Documentation/devicetree/bindings/hwmon/maxim,max20730.yaml
index 8af0d7458e62..8588d97ba6ec 100644
--- a/Documentation/devicetree/bindings/hwmon/maxim,max20730.yaml
+++ b/Documentation/devicetree/bindings/hwmon/maxim,max20730.yaml
@@ -25,6 +25,7 @@ description: |
properties:
compatible:
enum:
+ - maxim,max20710
- maxim,max20730
- maxim,max20734
- maxim,max20743
diff --git a/Documentation/devicetree/bindings/hwmon/national,lm90.yaml b/Documentation/devicetree/bindings/hwmon/national,lm90.yaml
index 4feb76919404..1b871f166e79 100644
--- a/Documentation/devicetree/bindings/hwmon/national,lm90.yaml
+++ b/Documentation/devicetree/bindings/hwmon/national,lm90.yaml
@@ -20,6 +20,7 @@ properties:
- dallas,max6646
- dallas,max6647
- dallas,max6649
+ - dallas,max6654
- dallas,max6657
- dallas,max6658
- dallas,max6659
@@ -36,6 +37,9 @@ properties:
- nuvoton,nct7717
- nuvoton,nct7718
- nxp,sa56004
+ - onnn,nct72
+ - onnn,nct214
+ - onnn,nct218
- onnn,nct1008
- ti,tmp451
- ti,tmp461
@@ -118,6 +122,7 @@ allOf:
- dallas,max6646
- dallas,max6647
- dallas,max6649
+ - dallas,max6654
- dallas,max6657
- dallas,max6658
- dallas,max6659
@@ -139,6 +144,9 @@ allOf:
- adi,adt7461
- adi,adt7461a
- adi,adt7481
+ - onnn,nct72
+ - onnn,nct214
+ - onnn,nct218
- onnn,nct1008
then:
patternProperties:
diff --git a/Documentation/devicetree/bindings/hwmon/pmbus/adi,adp1050.yaml b/Documentation/devicetree/bindings/hwmon/pmbus/adi,adp1050.yaml
index 10c2204bc3df..af7530093942 100644
--- a/Documentation/devicetree/bindings/hwmon/pmbus/adi,adp1050.yaml
+++ b/Documentation/devicetree/bindings/hwmon/pmbus/adi,adp1050.yaml
@@ -10,16 +10,27 @@ maintainers:
- Radu Sabau <radu.sabau@analog.com>
description: |
- The ADP1050 is used to monitor system voltages, currents and temperatures.
+ The ADP1050 and similar devices are used to monitor system voltages,
+ currents, power, and temperatures.
+
Through the PMBus interface, the ADP1050 targets isolated power supplies
and has four individual monitors for input/output voltage, input current
and temperature.
Datasheet:
https://www.analog.com/en/products/adp1050.html
+ https://www.analog.com/en/products/adp1051.html
+ https://www.analog.com/en/products/adp1055.html
+ https://www.analog.com/en/products/ltp8800-1a.html
+ https://www.analog.com/en/products/ltp8800-2.html
+ https://www.analog.com/en/products/ltp8800-4a.html
properties:
compatible:
- const: adi,adp1050
+ enum:
+ - adi,adp1050
+ - adi,adp1051
+ - adi,adp1055
+ - adi,ltp8800
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/hwmon/pmbus/isil,isl68137.yaml b/Documentation/devicetree/bindings/hwmon/pmbus/isil,isl68137.yaml
index bac5f8e352aa..3dc7f15484d2 100644
--- a/Documentation/devicetree/bindings/hwmon/pmbus/isil,isl68137.yaml
+++ b/Documentation/devicetree/bindings/hwmon/pmbus/isil,isl68137.yaml
@@ -56,6 +56,7 @@ properties:
- renesas,raa228228
- renesas,raa229001
- renesas,raa229004
+ - renesas,raa229621
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/hwmon/pmbus/ti,ucd90320.yaml b/Documentation/devicetree/bindings/hwmon/pmbus/ti,ucd90320.yaml
index f8bea1c0e94a..8f9ce00079df 100644
--- a/Documentation/devicetree/bindings/hwmon/pmbus/ti,ucd90320.yaml
+++ b/Documentation/devicetree/bindings/hwmon/pmbus/ti,ucd90320.yaml
@@ -23,7 +23,13 @@ description: |
properties:
compatible:
enum:
+ - ti,ucd9000
+ - ti,ucd9090
+ - ti,ucd90120
+ - ti,ucd90124
+ - ti,ucd90160
- ti,ucd90320
+ - ti,ucd90910
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/hwmon/ti,amc6821.yaml b/Documentation/devicetree/bindings/hwmon/ti,amc6821.yaml
index 9ca7356760a7..eb00756988be 100644
--- a/Documentation/devicetree/bindings/hwmon/ti,amc6821.yaml
+++ b/Documentation/devicetree/bindings/hwmon/ti,amc6821.yaml
@@ -32,6 +32,12 @@ properties:
$ref: fan-common.yaml#
unevaluatedProperties: false
+ properties:
+ cooling-levels:
+ description: PWM duty cycle values corresponding to thermal cooling states.
+ items:
+ maximum: 255
+
"#pwm-cells":
const: 2
description: |
diff --git a/Documentation/devicetree/bindings/hwmon/ti,ina2xx.yaml b/Documentation/devicetree/bindings/hwmon/ti,ina2xx.yaml
index d1fb7b9abda0..fa68b99ef2e2 100644
--- a/Documentation/devicetree/bindings/hwmon/ti,ina2xx.yaml
+++ b/Documentation/devicetree/bindings/hwmon/ti,ina2xx.yaml
@@ -25,6 +25,7 @@ properties:
- ti,ina219
- ti,ina220
- ti,ina226
+ - ti,ina228
- ti,ina230
- ti,ina231
- ti,ina233
@@ -107,6 +108,7 @@ allOf:
- ti,ina219
- ti,ina220
- ti,ina226
+ - ti,ina228
- ti,ina230
- ti,ina231
- ti,ina237
diff --git a/Documentation/devicetree/bindings/hwmon/ti,lm87.yaml b/Documentation/devicetree/bindings/hwmon/ti,lm87.yaml
index 63d8cf467806..5c0cdc0091b5 100644
--- a/Documentation/devicetree/bindings/hwmon/ti,lm87.yaml
+++ b/Documentation/devicetree/bindings/hwmon/ti,lm87.yaml
@@ -18,7 +18,9 @@ description: |
properties:
compatible:
- const: ti,lm87
+ enum:
+ - adi,adm1024
+ - ti,lm87
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/trivial-devices.yaml b/Documentation/devicetree/bindings/trivial-devices.yaml
index 08654ed4021b..f3dd18681aa6 100644
--- a/Documentation/devicetree/bindings/trivial-devices.yaml
+++ b/Documentation/devicetree/bindings/trivial-devices.yaml
@@ -450,6 +450,8 @@ properties:
- ti,tps53679
# TI Dual channel DCAP+ multiphase controller TPS53681
- ti,tps53681
+ # TI Dual channel DCAP+ multiphase controller TPS53685 with AMD-SVI3
+ - ti,tps53685
# TI Dual channel DCAP+ multiphase controller TPS53688
- ti,tps53688
# TI DC-DC converters on PMBus
diff --git a/Documentation/hwmon/adp1050.rst b/Documentation/hwmon/adp1050.rst
index 8fa937064886..32514084fbdc 100644
--- a/Documentation/hwmon/adp1050.rst
+++ b/Documentation/hwmon/adp1050.rst
@@ -13,6 +13,32 @@ Supported chips:
Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ADP1050.pdf
+ * Analog Devices ADP1051
+
+ Prefix: 'adp1051'
+
+ Addresses scanned: I2C 0x70 - 0x77
+
+ Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ADP1051.pdf
+
+ * Analog Devices ADP1055
+
+ Prefix: 'adp1055'
+
+ Addresses scanned: I2C 0x4B - 0x77
+
+ Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ADP1055.pdf
+
+ * Analog Devices LTP8800-1A/-2/-4A
+
+ Prefix: 'ltp8800'
+
+ Addresses scanned: -
+
+ Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/LTP8800-1A.pdf
+ https://www.analog.com/media/en/technical-documentation/data-sheets/LTP8800-2.pdf
+ https://www.analog.com/media/en/technical-documentation/data-sheets/LTP8800-4A.pdf
+
Authors:
- Radu Sabau <radu.sabau@analog.com>
@@ -21,14 +47,17 @@ Authors:
Description
-----------
-This driver supprts hardware monitoring for Analog Devices ADP1050 Digital
-Controller for Isolated Power Supply with PMBus interface.
+This driver supports hardware monitoring for Analog Devices ADP1050, ADP1051,
+and ADP1055 Digital Controller for Isolated Power Supply with PMBus interface,
+and the LTP8800 step-down μModule regulators.
-The ADP1050 is an advanced digital controller with a PMBus™
+The ADP1050, ADP1051, and ADP1055 are advanced digital controllers with PMBus™
interface targeting high density, high efficiency dc-to-dc power
-conversion used to monitor system temperatures, voltages and currents.
-Through the PMBus interface, the device can monitor input/output voltages,
-input current and temperature.
+conversion used to monitor system temperatures, voltages and currents. The
+LTP8800 is a family of step-down μModule regulators that provides microprocessor
+core voltage from 54V power distribution architecture. Through the PMBus
+interface, the device can monitor input/output voltages, input current and
+temperature.
Usage Notes
-----------
@@ -49,16 +78,46 @@ Sysfs Attributes
in1_label "vin"
in1_input Measured input voltage
in1_alarm Input voltage alarm
+in1_crit Critical maximum input voltage
+in1_crit_alarm Input voltage high alarm
+in1_lcrit Critical minimum input voltage
+in1_lcrit_alarm Input voltage critical low alarm
in2_label "vout1"
in2_input Measured output voltage
in2_crit Critical maximum output voltage
in2_crit_alarm Output voltage high alarm
in2_lcrit Critical minimum output voltage
in2_lcrit_alarm Output voltage critical low alarm
+in2_max Critical maximum output voltage
+in2_max_alarm Output voltage critical max alarm
+in2_min Critical minimum output voltage
+in2_min_alarm Output voltage critical min alarm
curr1_label "iin"
curr1_input Measured input current.
curr1_alarm Input current alarm
+curr1_crit Critical maximum input current
+curr1_crit_alarm Input current high alarm
+curr2_label "iout1"
+curr2_input Measured output current
+curr2_alarm Output current alarm
+curr2_crit Critical maximum output current
+curr2_crit_alarm Output current high alarm
+curr2_lcrit Critical minimum output current
+curr2_lcrit_alarm Output current critical low alarm
+curr2_max Critical maximum output current
+curr2_max_alarm Output current critical max alarm
+power1_label "pout1"
+power1_input Measured output power
+power1_crit Critical maximum output power
+power1_crit_alarm Output power high alarm
temp1_input Measured temperature
temp1_crit Critical high temperature
temp1_crit_alarm Chip temperature critical high alarm
+temp1_max Critical maximum temperature
+temp1_max_alarm Temperature critical max alarm
+temp2_input Measured temperature
+temp2_crit Critical high temperature
+temp2_crit_alarm Chip temperature critical high alarm
+temp2_max Critical maximum temperature
+temp2_max_alarm Temperature critical max alarm
================= ========================================
diff --git a/Documentation/hwmon/asus_ec_sensors.rst b/Documentation/hwmon/asus_ec_sensors.rst
index 816d1f9947ea..de2f2985f06f 100644
--- a/Documentation/hwmon/asus_ec_sensors.rst
+++ b/Documentation/hwmon/asus_ec_sensors.rst
@@ -11,6 +11,7 @@ Supported boards:
* Pro WS X570-ACE
* ProArt X570-CREATOR WIFI
* ProArt X670E-CREATOR WIFI
+ * ProArt X870E-CREATOR WIFI
* ProArt B550-CREATOR
* ROG CROSSHAIR VIII DARK HERO
* ROG CROSSHAIR VIII HERO (WI-FI)
@@ -29,6 +30,7 @@ Supported boards:
* ROG STRIX X570-F GAMING
* ROG STRIX X570-I GAMING
* ROG STRIX Z390-F GAMING
+ * ROG STRIX Z490-F GAMING
* ROG STRIX Z690-A GAMING WIFI D4
* ROG ZENITH II EXTREME
* ROG ZENITH II EXTREME ALPHA
diff --git a/Documentation/hwmon/corsair-psu.rst b/Documentation/hwmon/corsair-psu.rst
index 7ed794087f84..2e99cfd556a0 100644
--- a/Documentation/hwmon/corsair-psu.rst
+++ b/Documentation/hwmon/corsair-psu.rst
@@ -17,7 +17,7 @@ Supported devices:
Corsair HX1000i (Legacy and Series 2023)
- Corsair HX1200i (Legacy and Series 2023)
+ Corsair HX1200i (Legacy, Series 2023 and Series 2025)
Corsair HX1500i (Legacy and Series 2023)
diff --git a/Documentation/hwmon/tps53679.rst b/Documentation/hwmon/tps53679.rst
index 3b9561648c24..dd5e4a37375d 100644
--- a/Documentation/hwmon/tps53679.rst
+++ b/Documentation/hwmon/tps53679.rst
@@ -43,6 +43,14 @@ Supported chips:
Datasheet: https://www.ti.com/lit/gpn/TPS53681
+ * Texas Instruments TPS53685
+
+ Prefix: 'tps53685'
+
+ Addresses scanned: -
+
+ Datasheet: https://www.ti.com/lit/gpn/TPS53685
+
* Texas Instruments TPS53688
Prefix: 'tps53688'
diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c
index 5f2541c11fe9..8cefa14e1633 100644
--- a/drivers/hwmon/adt7475.c
+++ b/drivers/hwmon/adt7475.c
@@ -1704,12 +1704,15 @@ static int adt7475_pwm_properties_parse_reference_args(struct fwnode_handle *fwn
if (ret)
return ret;
- if (rargs.nargs != 4) {
+ if (rargs.nargs != 3 && rargs.nargs != 4) {
fwnode_handle_put(rargs.fwnode);
return -EINVAL;
}
- for (i = 0; i < 4; i++)
+ /* Let duty_cycle default to period */
+ args[3] = rargs.args[1];
+
+ for (i = 0; i < rargs.nargs; i++)
args[i] = rargs.args[i];
ret = _adt7475_pwm_properties_parse_args(args, cfg);
@@ -1724,11 +1727,22 @@ static int adt7475_pwm_properties_parse_args(struct fwnode_handle *fwnode,
{
int ret;
u32 args[4] = {};
+ size_t n_vals = fwnode_property_count_u32(fwnode, "pwms");
+
+ if (n_vals != 3 && n_vals != 4)
+ return -EOVERFLOW;
- ret = fwnode_property_read_u32_array(fwnode, "pwms", args, ARRAY_SIZE(args));
+ ret = fwnode_property_read_u32_array(fwnode, "pwms", args, n_vals);
if (ret)
return ret;
+ /*
+ * If there are no item to define the duty_cycle, default it to the
+ * period.
+ */
+ if (n_vals == 3)
+ args[3] = args[1];
+
return _adt7475_pwm_properties_parse_args(args, cfg);
}
diff --git a/drivers/hwmon/amc6821.c b/drivers/hwmon/amc6821.c
index 13a789cc85d2..d5f864b360b0 100644
--- a/drivers/hwmon/amc6821.c
+++ b/drivers/hwmon/amc6821.c
@@ -26,6 +26,7 @@
#include <linux/pwm.h>
#include <linux/regmap.h>
#include <linux/slab.h>
+#include <linux/thermal.h>
#include <dt-bindings/pwm/pwm.h>
@@ -126,6 +127,10 @@ module_param(init, int, 0444);
struct amc6821_data {
struct regmap *regmap;
struct mutex update_lock;
+ unsigned long fan_state;
+ unsigned long fan_max_state;
+ unsigned int *fan_cooling_levels;
+ enum pwm_polarity pwm_polarity;
};
/*
@@ -804,6 +809,65 @@ static const struct hwmon_chip_info amc6821_chip_info = {
.info = amc6821_info,
};
+static int amc6821_set_sw_dcy(struct amc6821_data *data, u8 duty_cycle)
+{
+ int ret;
+
+ ret = regmap_write(data->regmap, AMC6821_REG_DCY, duty_cycle);
+ if (ret)
+ return ret;
+
+ return regmap_update_bits(data->regmap, AMC6821_REG_CONF1,
+ AMC6821_CONF1_FDRC0 | AMC6821_CONF1_FDRC1, 0);
+}
+
+static int amc6821_get_max_state(struct thermal_cooling_device *cdev, unsigned long *state)
+{
+ struct amc6821_data *data = cdev->devdata;
+
+ if (!data)
+ return -EINVAL;
+
+ *state = data->fan_max_state;
+
+ return 0;
+}
+
+static int amc6821_get_cur_state(struct thermal_cooling_device *cdev, unsigned long *state)
+{
+ struct amc6821_data *data = cdev->devdata;
+
+ if (!data)
+ return -EINVAL;
+
+ *state = data->fan_state;
+
+ return 0;
+}
+
+static int amc6821_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state)
+{
+ struct amc6821_data *data = cdev->devdata;
+ int ret;
+
+ if (!data || state > data->fan_max_state)
+ return -EINVAL;
+
+ ret = amc6821_set_sw_dcy(data, data->fan_cooling_levels[state]);
+ if (ret)
+ return ret;
+
+ data->fan_state = state;
+
+ return 0;
+}
+
+static const struct thermal_cooling_device_ops amc6821_cooling_ops = {
+ .get_max_state = amc6821_get_max_state,
+ .get_cur_state = amc6821_get_cur_state,
+ .set_cur_state = amc6821_set_cur_state,
+};
+
/* Return 0 if detection is successful, -ENODEV otherwise */
static int amc6821_detect(struct i2c_client *client, struct i2c_board_info *info)
{
@@ -848,11 +912,11 @@ static int amc6821_detect(struct i2c_client *client, struct i2c_board_info *info
return 0;
}
-static enum pwm_polarity amc6821_pwm_polarity(struct i2c_client *client)
+static enum pwm_polarity amc6821_pwm_polarity(struct i2c_client *client,
+ struct device_node *fan_np)
{
enum pwm_polarity polarity = PWM_POLARITY_NORMAL;
struct of_phandle_args args;
- struct device_node *fan_np;
/*
* For backward compatibility, the pwminv module parameter takes
@@ -863,10 +927,6 @@ static enum pwm_polarity amc6821_pwm_polarity(struct i2c_client *client)
if (pwminv > 0)
return PWM_POLARITY_INVERSED;
- fan_np = of_get_child_by_name(client->dev.of_node, "fan");
- if (!fan_np)
- return PWM_POLARITY_NORMAL;
-
if (of_parse_phandle_with_args(fan_np, "pwms", "#pwm-cells", 0, &args))
goto out;
of_node_put(args.np);
@@ -877,10 +937,34 @@ static enum pwm_polarity amc6821_pwm_polarity(struct i2c_client *client)
if (args.args[1] & PWM_POLARITY_INVERTED)
polarity = PWM_POLARITY_INVERSED;
out:
- of_node_put(fan_np);
return polarity;
}
+static int amc6821_of_fan_read_data(struct i2c_client *client,
+ struct amc6821_data *data,
+ struct device_node *fan_np)
+{
+ int num;
+
+ data->pwm_polarity = amc6821_pwm_polarity(client, fan_np);
+
+ num = of_property_count_u32_elems(fan_np, "cooling-levels");
+ if (num <= 0)
+ return 0;
+
+ data->fan_max_state = num - 1;
+
+ data->fan_cooling_levels = devm_kcalloc(&client->dev, num,
+ sizeof(u32),
+ GFP_KERNEL);
+
+ if (!data->fan_cooling_levels)
+ return -ENOMEM;
+
+ return of_property_read_u32_array(fan_np, "cooling-levels",
+ data->fan_cooling_levels, num);
+}
+
static int amc6821_init_client(struct i2c_client *client, struct amc6821_data *data)
{
struct regmap *regmap = data->regmap;
@@ -902,7 +986,7 @@ static int amc6821_init_client(struct i2c_client *client, struct amc6821_data *d
return err;
regval = AMC6821_CONF1_START;
- if (amc6821_pwm_polarity(client) == PWM_POLARITY_INVERSED)
+ if (data->pwm_polarity == PWM_POLARITY_INVERSED)
regval |= AMC6821_CONF1_PWMINV;
err = regmap_update_bits(regmap, AMC6821_REG_CONF1,
@@ -911,6 +995,14 @@ static int amc6821_init_client(struct i2c_client *client, struct amc6821_data *d
regval);
if (err)
return err;
+
+ /* Software DCY-control mode with fan enabled when cooling-levels present */
+ if (data->fan_cooling_levels) {
+ err = amc6821_set_sw_dcy(data,
+ data->fan_cooling_levels[data->fan_max_state]);
+ if (err)
+ return err;
+ }
}
return 0;
}
@@ -944,6 +1036,7 @@ static int amc6821_probe(struct i2c_client *client)
struct amc6821_data *data;
struct device *hwmon_dev;
struct regmap *regmap;
+ struct device_node *fan_np __free(device_node) = NULL;
int err;
data = devm_kzalloc(dev, sizeof(struct amc6821_data), GFP_KERNEL);
@@ -956,6 +1049,14 @@ static int amc6821_probe(struct i2c_client *client)
"Failed to initialize regmap\n");
data->regmap = regmap;
+ fan_np = of_get_child_by_name(dev->of_node, "fan");
+ if (fan_np) {
+ err = amc6821_of_fan_read_data(client, data, fan_np);
+ if (err)
+ return dev_err_probe(dev, err,
+ "Failed to read fan device tree data\n");
+ }
+
err = amc6821_init_client(client, data);
if (err)
return err;
@@ -970,7 +1071,15 @@ static int amc6821_probe(struct i2c_client *client)
hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
data, &amc6821_chip_info,
amc6821_groups);
- return PTR_ERR_OR_ZERO(hwmon_dev);
+ if (IS_ERR(hwmon_dev))
+ return dev_err_probe(dev, PTR_ERR(hwmon_dev),
+ "Failed to initialize hwmon\n");
+
+ if (IS_ENABLED(CONFIG_THERMAL) && fan_np && data->fan_cooling_levels)
+ return PTR_ERR_OR_ZERO(devm_thermal_of_cooling_device_register(dev,
+ fan_np, client->name, data, &amc6821_cooling_ops));
+
+ return 0;
}
static const struct i2c_device_id amc6821_id[] = {
diff --git a/drivers/hwmon/asus-ec-sensors.c b/drivers/hwmon/asus-ec-sensors.c
index e0a95197c71b..4ac554731e98 100644
--- a/drivers/hwmon/asus-ec-sensors.c
+++ b/drivers/hwmon/asus-ec-sensors.c
@@ -165,7 +165,9 @@ enum board_family {
family_amd_400_series,
family_amd_500_series,
family_amd_600_series,
+ family_amd_800_series,
family_intel_300_series,
+ family_intel_400_series,
family_intel_600_series
};
@@ -259,6 +261,20 @@ static const struct ec_sensor_info sensors_family_amd_600[] = {
EC_SENSOR("Water_Out", hwmon_temp, 1, 0x01, 0x01),
};
+static const struct ec_sensor_info sensors_family_amd_800[] = {
+ [ec_sensor_temp_cpu] = EC_SENSOR("CPU", hwmon_temp, 1, 0x00, 0x30),
+ [ec_sensor_temp_cpu_package] =
+ EC_SENSOR("CPU Package", hwmon_temp, 1, 0x00, 0x31),
+ [ec_sensor_temp_mb] =
+ EC_SENSOR("Motherboard", hwmon_temp, 1, 0x00, 0x32),
+ [ec_sensor_temp_vrm] =
+ EC_SENSOR("VRM", hwmon_temp, 1, 0x00, 0x33),
+ [ec_sensor_temp_t_sensor] =
+ EC_SENSOR("T_Sensor", hwmon_temp, 1, 0x00, 0x36),
+ [ec_sensor_fan_cpu_opt] =
+ EC_SENSOR("CPU_Opt", hwmon_fan, 2, 0x00, 0xb0),
+};
+
static const struct ec_sensor_info sensors_family_intel_300[] = {
[ec_sensor_temp_chipset] =
EC_SENSOR("Chipset", hwmon_temp, 1, 0x00, 0x3a),
@@ -279,6 +295,20 @@ static const struct ec_sensor_info sensors_family_intel_300[] = {
EC_SENSOR("Water_Out", hwmon_temp, 1, 0x01, 0x01),
};
+static const struct ec_sensor_info sensors_family_intel_400[] = {
+ [ec_sensor_temp_chipset] =
+ EC_SENSOR("Chipset", hwmon_temp, 1, 0x00, 0x3a),
+ [ec_sensor_temp_cpu] = EC_SENSOR("CPU", hwmon_temp, 1, 0x00, 0x3b),
+ [ec_sensor_temp_mb] =
+ EC_SENSOR("Motherboard", hwmon_temp, 1, 0x00, 0x3c),
+ [ec_sensor_temp_t_sensor] =
+ EC_SENSOR("T_Sensor", hwmon_temp, 1, 0x00, 0x3d),
+ [ec_sensor_temp_vrm] = EC_SENSOR("VRM", hwmon_temp, 1, 0x00, 0x3e),
+ [ec_sensor_fan_cpu_opt] =
+ EC_SENSOR("CPU_Opt", hwmon_fan, 2, 0x00, 0xb0),
+ [ec_sensor_fan_vrm_hs] = EC_SENSOR("VRM HS", hwmon_fan, 2, 0x00, 0xb2),
+};
+
static const struct ec_sensor_info sensors_family_intel_600[] = {
[ec_sensor_temp_t_sensor] =
EC_SENSOR("T_Sensor", hwmon_temp, 1, 0x00, 0x3d),
@@ -362,6 +392,14 @@ static const struct ec_board_info board_info_pro_art_x670E_creator_wifi = {
.family = family_amd_600_series,
};
+static const struct ec_board_info board_info_pro_art_x870E_creator_wifi = {
+ .sensors = SENSOR_TEMP_CPU | SENSOR_TEMP_CPU_PACKAGE |
+ SENSOR_TEMP_MB | SENSOR_TEMP_VRM |
+ SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CPU_OPT,
+ .mutex_path = ACPI_GLOBAL_LOCK_PSEUDO_PATH,
+ .family = family_amd_800_series,
+};
+
static const struct ec_board_info board_info_pro_art_b550_creator = {
.sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
SENSOR_TEMP_T_SENSOR |
@@ -498,6 +536,18 @@ static const struct ec_board_info board_info_strix_z390_f_gaming = {
.family = family_intel_300_series,
};
+static const struct ec_board_info board_info_strix_z490_f_gaming = {
+ .sensors = SENSOR_TEMP_CHIPSET |
+ SENSOR_TEMP_CPU |
+ SENSOR_TEMP_MB |
+ SENSOR_TEMP_T_SENSOR |
+ SENSOR_TEMP_VRM |
+ SENSOR_FAN_CPU_OPT |
+ SENSOR_FAN_VRM_HS,
+ .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
+ .family = family_intel_400_series,
+};
+
static const struct ec_board_info board_info_strix_z690_a_gaming_wifi_d4 = {
.sensors = SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM,
.mutex_path = ASUS_HW_ACCESS_MUTEX_RMTW_ASMX,
@@ -548,6 +598,8 @@ static const struct dmi_system_id dmi_table[] = {
&board_info_pro_art_x570_creator_wifi),
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ProArt X670E-CREATOR WIFI",
&board_info_pro_art_x670E_creator_wifi),
+ DMI_EXACT_MATCH_ASUS_BOARD_NAME("ProArt X870E-CREATOR WIFI",
+ &board_info_pro_art_x870E_creator_wifi),
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ProArt B550-CREATOR",
&board_info_pro_art_b550_creator),
DMI_EXACT_MATCH_ASUS_BOARD_NAME("Pro WS X570-ACE",
@@ -586,6 +638,8 @@ static const struct dmi_system_id dmi_table[] = {
&board_info_strix_x570_i_gaming),
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX Z390-F GAMING",
&board_info_strix_z390_f_gaming),
+ DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX Z490-F GAMING",
+ &board_info_strix_z490_f_gaming),
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX Z690-A GAMING WIFI D4",
&board_info_strix_z690_a_gaming_wifi_d4),
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG ZENITH II EXTREME",
@@ -1058,9 +1112,15 @@ static int asus_ec_probe(struct platform_device *pdev)
case family_amd_600_series:
ec_data->sensors_info = sensors_family_amd_600;
break;
+ case family_amd_800_series:
+ ec_data->sensors_info = sensors_family_amd_800;
+ break;
case family_intel_300_series:
ec_data->sensors_info = sensors_family_intel_300;
break;
+ case family_intel_400_series:
+ ec_data->sensors_info = sensors_family_intel_400;
+ break;
case family_intel_600_series:
ec_data->sensors_info = sensors_family_intel_600;
break;
diff --git a/drivers/hwmon/corsair-psu.c b/drivers/hwmon/corsair-psu.c
index f8f22b8a67cd..6b5c8f200780 100644
--- a/drivers/hwmon/corsair-psu.c
+++ b/drivers/hwmon/corsair-psu.c
@@ -885,6 +885,7 @@ static const struct hid_device_id corsairpsu_idtable[] = {
{ HID_USB_DEVICE(0x1b1c, 0x1c1e) }, /* Corsair HX1000i Series 2023 */
{ HID_USB_DEVICE(0x1b1c, 0x1c1f) }, /* Corsair HX1500i Legacy and Series 2023 */
{ HID_USB_DEVICE(0x1b1c, 0x1c23) }, /* Corsair HX1200i Series 2023 */
+ { HID_USB_DEVICE(0x1b1c, 0x1c27) }, /* Corsair HX1200i Series 2025 */
{ },
};
MODULE_DEVICE_TABLE(hid, corsairpsu_idtable);
diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c
index 234c54956a4b..60809289f816 100644
--- a/drivers/hwmon/emc2305.c
+++ b/drivers/hwmon/emc2305.c
@@ -11,6 +11,9 @@
#include <linux/module.h>
#include <linux/platform_data/emc2305.h>
#include <linux/thermal.h>
+#include <linux/pwm.h>
+#include <linux/of_device.h>
+#include <linux/util_macros.h>
#define EMC2305_REG_DRIVE_FAIL_STATUS 0x27
#define EMC2305_REG_VENDOR 0xfe
@@ -23,6 +26,12 @@
#define EMC2305_TACH_REGS_UNUSE_BITS 3
#define EMC2305_TACH_CNT_MULTIPLIER 0x02
#define EMC2305_TACH_RANGE_MIN 480
+#define EMC2305_DEFAULT_OUTPUT 0x0
+#define EMC2305_DEFAULT_POLARITY 0x0
+#define EMC2305_REG_POLARITY 0x2a
+#define EMC2305_REG_DRIVE_PWM_OUT 0x2b
+#define EMC2305_OPEN_DRAIN 0x0
+#define EMC2305_PUSH_PULL 0x1
#define EMC2305_PWM_DUTY2STATE(duty, max_state, pwm_max) \
DIV_ROUND_CLOSEST((duty) * (max_state), (pwm_max))
@@ -39,6 +48,9 @@
#define EMC2305_REG_FAN_MIN_DRIVE(n) (0x38 + 0x10 * (n))
#define EMC2305_REG_FAN_TACH(n) (0x3e + 0x10 * (n))
+/* Supported base PWM frequencies */
+static const unsigned int base_freq_table[] = { 2441, 4882, 19530, 26000 };
+
enum emc230x_product_id {
EMC2305 = 0x34,
EMC2303 = 0x35,
@@ -89,8 +101,11 @@ struct emc2305_cdev_data {
* @hwmon_dev: hwmon device
* @max_state: maximum cooling state of the cooling device
* @pwm_num: number of PWM channels
+ * @pwm_output_mask: PWM output mask
+ * @pwm_polarity_mask: PWM polarity mask
* @pwm_separate: separate PWM settings for every channel
* @pwm_min: array of minimum PWM per channel
+ * @pwm_freq: array of PWM frequency per channel
* @cdev_data: array of cooling devices data
*/
struct emc2305_data {
@@ -98,8 +113,11 @@ struct emc2305_data {
struct device *hwmon_dev;
u8 max_state;
u8 pwm_num;
+ u8 pwm_output_mask;
+ u8 pwm_polarity_mask;
bool pwm_separate;
u8 pwm_min[EMC2305_PWM_MAX];
+ u16 pwm_freq[EMC2305_PWM_MAX];
struct emc2305_cdev_data cdev_data[EMC2305_PWM_MAX];
};
@@ -281,7 +299,7 @@ static int emc2305_set_pwm(struct device *dev, long val, int channel)
return 0;
}
-static int emc2305_set_single_tz(struct device *dev, int idx)
+static int emc2305_set_single_tz(struct device *dev, struct device_node *fan_node, int idx)
{
struct emc2305_data *data = dev_get_drvdata(dev);
long pwm;
@@ -291,7 +309,7 @@ static int emc2305_set_single_tz(struct device *dev, int idx)
pwm = data->pwm_min[cdev_idx];
data->cdev_data[cdev_idx].cdev =
- devm_thermal_of_cooling_device_register(dev, dev->of_node,
+ devm_thermal_of_cooling_device_register(dev, fan_node,
emc2305_fan_name[idx], data,
&emc2305_cooling_ops);
@@ -299,6 +317,12 @@ static int emc2305_set_single_tz(struct device *dev, int idx)
dev_err(dev, "Failed to register cooling device %s\n", emc2305_fan_name[idx]);
return PTR_ERR(data->cdev_data[cdev_idx].cdev);
}
+
+ if (data->cdev_data[cdev_idx].cur_state > 0)
+ /* Update pwm when temperature is above trips */
+ pwm = EMC2305_PWM_STATE2DUTY(data->cdev_data[cdev_idx].cur_state,
+ data->max_state, EMC2305_FAN_MAX);
+
/* Set minimal PWM speed. */
if (data->pwm_separate) {
ret = emc2305_set_pwm(dev, pwm, cdev_idx);
@@ -312,10 +336,10 @@ static int emc2305_set_single_tz(struct device *dev, int idx)
}
}
data->cdev_data[cdev_idx].cur_state =
- EMC2305_PWM_DUTY2STATE(data->pwm_min[cdev_idx], data->max_state,
+ EMC2305_PWM_DUTY2STATE(pwm, data->max_state,
EMC2305_FAN_MAX);
data->cdev_data[cdev_idx].last_hwmon_state =
- EMC2305_PWM_DUTY2STATE(data->pwm_min[cdev_idx], data->max_state,
+ EMC2305_PWM_DUTY2STATE(pwm, data->max_state,
EMC2305_FAN_MAX);
return 0;
}
@@ -326,10 +350,10 @@ static int emc2305_set_tz(struct device *dev)
int i, ret;
if (!data->pwm_separate)
- return emc2305_set_single_tz(dev, 0);
+ return emc2305_set_single_tz(dev, dev->of_node, 0);
for (i = 0; i < data->pwm_num; i++) {
- ret = emc2305_set_single_tz(dev, i + 1);
+ ret = emc2305_set_single_tz(dev, dev->of_node, i + 1);
if (ret)
return ret;
}
@@ -511,15 +535,85 @@ static int emc2305_identify(struct device *dev)
return 0;
}
+static int emc2305_of_parse_pwm_child(struct device *dev,
+ struct device_node *child,
+ struct emc2305_data *data)
+{ u32 ch;
+ int ret;
+ struct of_phandle_args args;
+
+ ret = of_property_read_u32(child, "reg", &ch);
+ if (ret) {
+ dev_err(dev, "missing reg property of %pOFn\n", child);
+ return ret;
+ }
+
+ ret = of_parse_phandle_with_args(child, "pwms", "#pwm-cells", 0, &args);
+
+ if (ret)
+ return ret;
+
+ if (args.args_count > 0) {
+ data->pwm_freq[ch] = find_closest(args.args[0], base_freq_table,
+ ARRAY_SIZE(base_freq_table));
+ } else {
+ data->pwm_freq[ch] = base_freq_table[3];
+ }
+
+ if (args.args_count > 1) {
+ if (args.args[1] == PWM_POLARITY_NORMAL || args.args[1] == PWM_POLARITY_INVERSED)
+ data->pwm_polarity_mask |= args.args[1] << ch;
+ else
+ dev_err(dev, "Wrong PWM polarity config provided: %d\n", args.args[0]);
+ } else {
+ data->pwm_polarity_mask |= PWM_POLARITY_NORMAL << ch;
+ }
+
+ if (args.args_count > 2) {
+ if (args.args[2] == EMC2305_PUSH_PULL || args.args[2] <= EMC2305_OPEN_DRAIN)
+ data->pwm_output_mask |= args.args[2] << ch;
+ else
+ dev_err(dev, "Wrong PWM output config provided: %d\n", args.args[1]);
+ } else {
+ data->pwm_output_mask |= EMC2305_OPEN_DRAIN << ch;
+ }
+
+ return 0;
+}
+
+static int emc2305_probe_childs_from_dt(struct device *dev)
+{
+ struct emc2305_data *data = dev_get_drvdata(dev);
+ struct device_node *child;
+ int ret, count = 0;
+
+ data->pwm_output_mask = 0x0;
+ data->pwm_polarity_mask = 0x0;
+
+ for_each_child_of_node(dev->of_node, child) {
+ if (of_property_present(child, "reg")) {
+ ret = emc2305_of_parse_pwm_child(dev, child, data);
+ if (ret) {
+ of_node_put(child);
+ continue;
+ }
+ count++;
+ }
+ }
+ return count;
+}
+
static int emc2305_probe(struct i2c_client *client)
{
struct i2c_adapter *adapter = client->adapter;
struct device *dev = &client->dev;
+ struct device_node *child;
struct emc2305_data *data;
struct emc2305_platform_data *pdata;
int vendor;
int ret;
int i;
+ int pwm_childs;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
return -ENODEV;
@@ -539,22 +633,40 @@ static int emc2305_probe(struct i2c_client *client)
if (ret)
return ret;
+ pwm_childs = emc2305_probe_childs_from_dt(dev);
+
pdata = dev_get_platdata(&client->dev);
- if (pdata) {
- if (!pdata->max_state || pdata->max_state > EMC2305_FAN_MAX_STATE)
- return -EINVAL;
- data->max_state = pdata->max_state;
- /*
- * Validate a number of active PWM channels. Note that
- * configured number can be less than the actual maximum
- * supported by the device.
- */
- if (!pdata->pwm_num || pdata->pwm_num > EMC2305_PWM_MAX)
- return -EINVAL;
- data->pwm_num = pdata->pwm_num;
- data->pwm_separate = pdata->pwm_separate;
- for (i = 0; i < EMC2305_PWM_MAX; i++)
- data->pwm_min[i] = pdata->pwm_min[i];
+
+ if (!pwm_childs) {
+ if (pdata) {
+ if (!pdata->max_state || pdata->max_state > EMC2305_FAN_MAX_STATE)
+ return -EINVAL;
+ data->max_state = pdata->max_state;
+ /*
+ * Validate a number of active PWM channels. Note that
+ * configured number can be less than the actual maximum
+ * supported by the device.
+ */
+ if (!pdata->pwm_num || pdata->pwm_num > EMC2305_PWM_MAX)
+ return -EINVAL;
+ data->pwm_num = pdata->pwm_num;
+ data->pwm_output_mask = pdata->pwm_output_mask;
+ data->pwm_polarity_mask = pdata->pwm_polarity_mask;
+ data->pwm_separate = pdata->pwm_separate;
+ for (i = 0; i < EMC2305_PWM_MAX; i++) {
+ data->pwm_min[i] = pdata->pwm_min[i];
+ data->pwm_freq[i] = pdata->pwm_freq[i];
+ }
+ } else {
+ data->max_state = EMC2305_FAN_MAX_STATE;
+ data->pwm_separate = false;
+ data->pwm_output_mask = EMC2305_DEFAULT_OUTPUT;
+ data->pwm_polarity_mask = EMC2305_DEFAULT_POLARITY;
+ for (i = 0; i < EMC2305_PWM_MAX; i++) {
+ data->pwm_min[i] = EMC2305_FAN_MIN;
+ data->pwm_freq[i] = base_freq_table[3];
+ }
+ }
} else {
data->max_state = EMC2305_FAN_MAX_STATE;
data->pwm_separate = false;
@@ -568,11 +680,32 @@ static int emc2305_probe(struct i2c_client *client)
return PTR_ERR(data->hwmon_dev);
if (IS_REACHABLE(CONFIG_THERMAL)) {
- ret = emc2305_set_tz(dev);
- if (ret != 0)
- return ret;
+ /* Parse and check for the available PWM child nodes */
+ if (pwm_childs > 0) {
+ i = 0;
+ for_each_child_of_node(dev->of_node, child) {
+ ret = emc2305_set_single_tz(dev, child, i);
+ if (ret != 0)
+ return ret;
+ i++;
+ }
+ } else {
+ ret = emc2305_set_tz(dev);
+ if (ret != 0)
+ return ret;
+ }
}
+ ret = i2c_smbus_write_byte_data(client, EMC2305_REG_DRIVE_PWM_OUT,
+ data->pwm_output_mask);
+ if (ret < 0)
+ dev_err(dev, "Failed to configure pwm output, using default\n");
+
+ ret = i2c_smbus_write_byte_data(client, EMC2305_REG_POLARITY,
+ data->pwm_polarity_mask);
+ if (ret < 0)
+ dev_err(dev, "Failed to configure pwm polarity, using default\n");
+
for (i = 0; i < data->pwm_num; i++) {
ret = i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_MIN_DRIVE(i),
data->pwm_min[i]);
diff --git a/drivers/hwmon/gsc-hwmon.c b/drivers/hwmon/gsc-hwmon.c
index 0f9af82cebec..105b9f9dbec3 100644
--- a/drivers/hwmon/gsc-hwmon.c
+++ b/drivers/hwmon/gsc-hwmon.c
@@ -64,7 +64,7 @@ static ssize_t pwm_auto_point_temp_show(struct device *dev,
return ret;
ret = regs[0] | regs[1] << 8;
- return sprintf(buf, "%d\n", ret * 10);
+ return sprintf(buf, "%d\n", ret * 100);
}
static ssize_t pwm_auto_point_temp_store(struct device *dev,
@@ -99,7 +99,7 @@ static ssize_t pwm_auto_point_pwm_show(struct device *dev,
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- return sprintf(buf, "%d\n", 255 * (50 + (attr->index * 10)));
+ return sprintf(buf, "%d\n", 255 * (50 + (attr->index * 10)) / 100);
}
static SENSOR_DEVICE_ATTR_RO(pwm1_auto_point1_pwm, pwm_auto_point_pwm, 0);
diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c
index 157e232aace0..daed437d34a4 100644
--- a/drivers/hwmon/ibmaem.c
+++ b/drivers/hwmon/ibmaem.c
@@ -349,7 +349,7 @@ static void aem_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
static int aem_read_sensor(struct aem_data *data, u8 elt, u8 reg,
void *buf, size_t size)
{
- int rs_size, res;
+ int rs_size;
struct aem_read_sensor_req rs_req;
/* Use preallocated rx buffer */
struct aem_read_sensor_resp *rs_resp = data->rs_resp;
@@ -383,17 +383,12 @@ static int aem_read_sensor(struct aem_data *data, u8 elt, u8 reg,
aem_send_message(ipmi);
- res = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT);
- if (!res) {
- res = -ETIMEDOUT;
- goto out;
- }
+ if (!wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT))
+ return -ETIMEDOUT;
if (ipmi->rx_result || ipmi->rx_msg_len != rs_size ||
- memcmp(&rs_resp->id, &system_x_id, sizeof(system_x_id))) {
- res = -ENOENT;
- goto out;
- }
+ memcmp(&rs_resp->id, &system_x_id, sizeof(system_x_id)))
+ return -ENOENT;
switch (size) {
case 1: {
@@ -417,10 +412,8 @@ static int aem_read_sensor(struct aem_data *data, u8 elt, u8 reg,
break;
}
}
- res = 0;
-out:
- return res;
+ return 0;
}
/* Update AEM energy registers */
@@ -491,7 +484,6 @@ static void aem_delete(struct aem_data *data)
/* Retrieve version and module handle for an AEM1 instance */
static int aem_find_aem1_count(struct aem_ipmi_data *data)
{
- int res;
struct aem_find_firmware_req ff_req;
struct aem_find_firmware_resp ff_resp;
@@ -508,8 +500,7 @@ static int aem_find_aem1_count(struct aem_ipmi_data *data)
aem_send_message(data);
- res = wait_for_completion_timeout(&data->read_complete, IPMI_TIMEOUT);
- if (!res)
+ if (!wait_for_completion_timeout(&data->read_complete, IPMI_TIMEOUT))
return -ETIMEDOUT;
if (data->rx_result || data->rx_msg_len != sizeof(ff_resp) ||
@@ -632,7 +623,6 @@ static int aem_find_aem2(struct aem_ipmi_data *data,
struct aem_find_instance_resp *fi_resp,
int instance_num)
{
- int res;
struct aem_find_instance_req fi_req;
fi_req.id = system_x_id;
@@ -648,8 +638,7 @@ static int aem_find_aem2(struct aem_ipmi_data *data,
aem_send_message(data);
- res = wait_for_completion_timeout(&data->read_complete, IPMI_TIMEOUT);
- if (!res)
+ if (!wait_for_completion_timeout(&data->read_complete, IPMI_TIMEOUT))
return -ETIMEDOUT;
if (data->rx_result || data->rx_msg_len != sizeof(*fi_resp) ||
diff --git a/drivers/hwmon/ina238.c b/drivers/hwmon/ina238.c
index 9a5fd16a4ec2..5a394eeff676 100644
--- a/drivers/hwmon/ina238.c
+++ b/drivers/hwmon/ina238.c
@@ -6,6 +6,7 @@
* Copyright (C) 2021 Nathan Rossi <nathan.rossi@digi.com>
*/
+#include <linux/bitops.h>
#include <linux/err.h>
#include <linux/hwmon.h>
#include <linux/i2c.h>
@@ -41,7 +42,7 @@
#define INA238_CONFIG_ADCRANGE BIT(4)
#define SQ52206_CONFIG_ADCRANGE_HIGH BIT(4)
-#define SQ52206_CONFIG_ADCRANGE_LOW BIT(3)
+#define SQ52206_CONFIG_ADCRANGE_LOW BIT(3)
#define INA238_DIAG_ALERT_TMPOL BIT(7)
#define INA238_DIAG_ALERT_SHNTOL BIT(6)
@@ -104,9 +105,10 @@
#define INA238_SHUNT_VOLTAGE_LSB 5 /* 5 uV/lsb */
#define INA238_BUS_VOLTAGE_LSB 3125 /* 3.125 mV/lsb */
-#define INA238_DIE_TEMP_LSB 1250000 /* 125.0000 mC/lsb */
+#define INA238_DIE_TEMP_LSB 1250000 /* 125.0000 mC/lsb */
#define SQ52206_BUS_VOLTAGE_LSB 3750 /* 3.75 mV/lsb */
#define SQ52206_DIE_TEMP_LSB 78125 /* 7.8125 mC/lsb */
+#define INA228_DIE_TEMP_LSB 78125 /* 7.8125 mC/lsb */
static const struct regmap_config ina238_regmap_config = {
.max_register = INA238_REGISTERS,
@@ -114,16 +116,17 @@ static const struct regmap_config ina238_regmap_config = {
.val_bits = 16,
};
-enum ina238_ids { ina238, ina237, sq52206 };
+enum ina238_ids { ina238, ina237, sq52206, ina228 };
struct ina238_config {
+ bool has_20bit_voltage_current; /* vshunt, vbus and current are 20-bit fields */
bool has_power_highest; /* chip detection power peak */
- bool has_energy; /* chip detection energy */
- u8 temp_shift; /* fixed parameters for temp calculate */
+ bool has_energy; /* chip detection energy */
+ u8 temp_shift; /* fixed parameters for temp calculate */
u32 power_calculate_factor; /* fixed parameters for power calculate */
- u16 config_default; /* Power-on default state */
+ u16 config_default; /* Power-on default state */
int bus_voltage_lsb; /* use for temperature calculate, uV/lsb */
- int temp_lsb; /* use for temperature calculate */
+ int temp_lsb; /* use for temperature calculate */
};
struct ina238_data {
@@ -137,6 +140,7 @@ struct ina238_data {
static const struct ina238_config ina238_config[] = {
[ina238] = {
+ .has_20bit_voltage_current = false,
.has_energy = false,
.has_power_highest = false,
.temp_shift = 4,
@@ -146,6 +150,7 @@ static const struct ina238_config ina238_config[] = {
.temp_lsb = INA238_DIE_TEMP_LSB,
},
[ina237] = {
+ .has_20bit_voltage_current = false,
.has_energy = false,
.has_power_highest = false,
.temp_shift = 4,
@@ -155,6 +160,7 @@ static const struct ina238_config ina238_config[] = {
.temp_lsb = INA238_DIE_TEMP_LSB,
},
[sq52206] = {
+ .has_20bit_voltage_current = false,
.has_energy = true,
.has_power_highest = true,
.temp_shift = 0,
@@ -163,6 +169,16 @@ static const struct ina238_config ina238_config[] = {
.bus_voltage_lsb = SQ52206_BUS_VOLTAGE_LSB,
.temp_lsb = SQ52206_DIE_TEMP_LSB,
},
+ [ina228] = {
+ .has_20bit_voltage_current = true,
+ .has_energy = true,
+ .has_power_highest = false,
+ .temp_shift = 0,
+ .power_calculate_factor = 20,
+ .config_default = INA238_CONFIG_DEFAULT,
+ .bus_voltage_lsb = INA238_BUS_VOLTAGE_LSB,
+ .temp_lsb = INA228_DIE_TEMP_LSB,
+ },
};
static int ina238_read_reg24(const struct i2c_client *client, u8 reg, u32 *val)
@@ -199,6 +215,65 @@ static int ina238_read_reg40(const struct i2c_client *client, u8 reg, u64 *val)
return 0;
}
+static int ina238_read_field_s20(const struct i2c_client *client, u8 reg, s32 *val)
+{
+ u32 regval;
+ int err;
+
+ err = ina238_read_reg24(client, reg, &regval);
+ if (err)
+ return err;
+
+ /* bits 3-0 Reserved, always zero */
+ regval >>= 4;
+
+ *val = sign_extend32(regval, 19);
+
+ return 0;
+}
+
+static int ina228_read_shunt_voltage(struct device *dev, u32 attr, int channel,
+ long *val)
+{
+ struct ina238_data *data = dev_get_drvdata(dev);
+ int regval;
+ int err;
+
+ err = ina238_read_field_s20(data->client, INA238_SHUNT_VOLTAGE, &regval);
+ if (err)
+ return err;
+
+ /*
+ * gain of 1 -> LSB / 4
+ * This field has 16 bit on ina238. ina228 adds another 4 bits of
+ * precision. ina238 conversion factors can still be applied when
+ * dividing by 16.
+ */
+ *val = (regval * INA238_SHUNT_VOLTAGE_LSB) * data->gain / (1000 * 4) / 16;
+ return 0;
+}
+
+static int ina228_read_bus_voltage(struct device *dev, u32 attr, int channel,
+ long *val)
+{
+ struct ina238_data *data = dev_get_drvdata(dev);
+ int regval;
+ int err;
+
+ err = ina238_read_field_s20(data->client, INA238_BUS_VOLTAGE, &regval);
+ if (err)
+ return err;
+
+ /*
+ * gain of 1 -> LSB / 4
+ * This field has 16 bit on ina238. ina228 adds another 4 bits of
+ * precision. ina238 conversion factors can still be applied when
+ * dividing by 16.
+ */
+ *val = (regval * data->config->bus_voltage_lsb) / 1000 / 16;
+ return 0;
+}
+
static int ina238_read_in(struct device *dev, u32 attr, int channel,
long *val)
{
@@ -211,6 +286,8 @@ static int ina238_read_in(struct device *dev, u32 attr, int channel,
case 0:
switch (attr) {
case hwmon_in_input:
+ if (data->config->has_20bit_voltage_current)
+ return ina228_read_shunt_voltage(dev, attr, channel, val);
reg = INA238_SHUNT_VOLTAGE;
break;
case hwmon_in_max:
@@ -234,6 +311,8 @@ static int ina238_read_in(struct device *dev, u32 attr, int channel,
case 1:
switch (attr) {
case hwmon_in_input:
+ if (data->config->has_20bit_voltage_current)
+ return ina228_read_bus_voltage(dev, attr, channel, val);
reg = INA238_BUS_VOLTAGE;
break;
case hwmon_in_max:
@@ -271,7 +350,7 @@ static int ina238_read_in(struct device *dev, u32 attr, int channel,
if (channel == 0)
/* gain of 1 -> LSB / 4 */
*val = (regval * INA238_SHUNT_VOLTAGE_LSB) *
- data->gain / (1000 * 4);
+ data->gain / (1000 * 4);
else
*val = (regval * data->config->bus_voltage_lsb) / 1000;
break;
@@ -341,13 +420,25 @@ static int ina238_read_current(struct device *dev, u32 attr, long *val)
switch (attr) {
case hwmon_curr_input:
- err = regmap_read(data->regmap, INA238_CURRENT, &regval);
- if (err < 0)
- return err;
+ if (data->config->has_20bit_voltage_current) {
+ err = ina238_read_field_s20(data->client, INA238_CURRENT, &regval);
+ if (err)
+ return err;
+ } else {
+ err = regmap_read(data->regmap, INA238_CURRENT, &regval);
+ if (err < 0)
+ return err;
+ /* sign-extend */
+ regval = (s16)regval;
+ }
/* Signed register, fixed 1mA current lsb. result in mA */
- *val = div_s64((s16)regval * INA238_FIXED_SHUNT * data->gain,
+ *val = div_s64((s64)regval * INA238_FIXED_SHUNT * data->gain,
data->rshunt * 4);
+
+ /* Account for 4 bit offset */
+ if (data->config->has_20bit_voltage_current)
+ *val /= 16;
break;
default:
return -EOPNOTSUPP;
@@ -370,7 +461,7 @@ static int ina238_read_power(struct device *dev, u32 attr, long *val)
return err;
/* Fixed 1mA lsb, scaled by 1000000 to have result in uW */
- power = div_u64(regval * 1000ULL * INA238_FIXED_SHUNT * data->gain *
+ power = div_u64(regval * 1000ULL * INA238_FIXED_SHUNT * data->gain *
data->config->power_calculate_factor, 4 * 100 * data->rshunt);
/* Clamp value to maximum value of long */
*val = clamp_val(power, 0, LONG_MAX);
@@ -381,7 +472,7 @@ static int ina238_read_power(struct device *dev, u32 attr, long *val)
return err;
/* Fixed 1mA lsb, scaled by 1000000 to have result in uW */
- power = div_u64(regval * 1000ULL * INA238_FIXED_SHUNT * data->gain *
+ power = div_u64(regval * 1000ULL * INA238_FIXED_SHUNT * data->gain *
data->config->power_calculate_factor, 4 * 100 * data->rshunt);
/* Clamp value to maximum value of long */
*val = clamp_val(power, 0, LONG_MAX);
@@ -395,7 +486,7 @@ static int ina238_read_power(struct device *dev, u32 attr, long *val)
* Truncated 24-bit compare register, lower 8-bits are
* truncated. Same conversion to/from uW as POWER register.
*/
- power = div_u64((regval << 8) * 1000ULL * INA238_FIXED_SHUNT * data->gain *
+ power = div_u64((regval << 8) * 1000ULL * INA238_FIXED_SHUNT * data->gain *
data->config->power_calculate_factor, 4 * 100 * data->rshunt);
/* Clamp value to maximum value of long */
*val = clamp_val(power, 0, LONG_MAX);
@@ -448,7 +539,7 @@ static int ina238_read_temp(struct device *dev, u32 attr, long *val)
return err;
/* Signed, result in mC */
*val = div_s64(((s64)((s16)regval) >> data->config->temp_shift) *
- (s64)data->config->temp_lsb, 10000);
+ (s64)data->config->temp_lsb, 10000);
break;
case hwmon_temp_max:
err = regmap_read(data->regmap, INA238_TEMP_LIMIT, &regval);
@@ -456,7 +547,7 @@ static int ina238_read_temp(struct device *dev, u32 attr, long *val)
return err;
/* Signed, result in mC */
*val = div_s64(((s64)((s16)regval) >> data->config->temp_shift) *
- (s64)data->config->temp_lsb, 10000);
+ (s64)data->config->temp_lsb, 10000);
break;
case hwmon_temp_max_alarm:
err = regmap_read(data->regmap, INA238_DIAG_ALERT, &regval);
@@ -501,8 +592,8 @@ static ssize_t energy1_input_show(struct device *dev,
return ret;
/* result in uJ */
- energy = div_u64(regval * INA238_FIXED_SHUNT * data->gain * 16 * 10 *
- data->config->power_calculate_factor, 4 * data->rshunt);
+ energy = div_u64(regval * INA238_FIXED_SHUNT * data->gain * 16 * 10 *
+ data->config->power_calculate_factor, 4 * data->rshunt);
return sysfs_emit(buf, "%llu\n", energy);
}
@@ -750,6 +841,7 @@ static int ina238_probe(struct i2c_client *client)
}
static const struct i2c_device_id ina238_id[] = {
+ { "ina228", ina228 },
{ "ina237", ina237 },
{ "ina238", ina238 },
{ "sq52206", sq52206 },
@@ -759,6 +851,10 @@ MODULE_DEVICE_TABLE(i2c, ina238_id);
static const struct of_device_id __maybe_unused ina238_of_match[] = {
{
+ .compatible = "ti,ina228",
+ .data = (void *)ina228
+ },
+ {
.compatible = "ti,ina237",
.data = (void *)ina237
},
diff --git a/drivers/hwmon/ltc4282.c b/drivers/hwmon/ltc4282.c
index f607fe8f7937..dbb30abcd343 100644
--- a/drivers/hwmon/ltc4282.c
+++ b/drivers/hwmon/ltc4282.c
@@ -177,13 +177,15 @@ static const unsigned int ltc4282_out_rates[] = {
LTC4282_CLKOUT_CNV, LTC4282_CLKOUT_SYSTEM
};
-static long ltc4282_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
+static int ltc4282_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
{
- int idx = find_closest(rate, ltc4282_out_rates,
+ int idx = find_closest(req->rate, ltc4282_out_rates,
ARRAY_SIZE(ltc4282_out_rates));
- return ltc4282_out_rates[idx];
+ req->rate = ltc4282_out_rates[idx];
+
+ return 0;
}
static unsigned long ltc4282_recalc_rate(struct clk_hw *hw,
@@ -1124,7 +1126,7 @@ static ssize_t ltc4282_energy_show(struct device *dev,
static const struct clk_ops ltc4282_ops = {
.recalc_rate = ltc4282_recalc_rate,
- .round_rate = ltc4282_round_rate,
+ .determine_rate = ltc4282_determine_rate,
.set_rate = ltc4282_set_rate,
.disable = ltc4282_disable,
};
@@ -1596,7 +1598,7 @@ static const struct hwmon_ops ltc4282_hwmon_ops = {
.read_string = ltc4282_read_labels,
};
-static const struct hwmon_chip_info ltc2947_chip_info = {
+static const struct hwmon_chip_info ltc4282_chip_info = {
.ops = &ltc4282_hwmon_ops,
.info = ltc4282_info,
};
@@ -1717,7 +1719,7 @@ static int ltc4282_probe(struct i2c_client *i2c)
mutex_init(&st->lock);
hwmon = devm_hwmon_device_register_with_info(dev, "ltc4282", st,
- &ltc2947_chip_info,
+ &ltc4282_chip_info,
ltc4282_groups);
if (IS_ERR(hwmon))
return PTR_ERR(hwmon);
diff --git a/drivers/hwmon/max31827.c b/drivers/hwmon/max31827.c
index 48e8f8ba4d05..a31c7b655da1 100644
--- a/drivers/hwmon/max31827.c
+++ b/drivers/hwmon/max31827.c
@@ -445,7 +445,7 @@ static ssize_t temp1_resolution_show(struct device *dev,
val = FIELD_GET(MAX31827_CONFIGURATION_RESOLUTION_MASK, val);
- return scnprintf(buf, PAGE_SIZE, "%u\n", max31827_resolutions[val]);
+ return sysfs_emit(buf, "%u\n", max31827_resolutions[val]);
}
static ssize_t temp1_resolution_store(struct device *dev,
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
index 441f984a859d..55e492452ce8 100644
--- a/drivers/hwmon/pmbus/Kconfig
+++ b/drivers/hwmon/pmbus/Kconfig
@@ -67,6 +67,15 @@ config SENSORS_ADP1050
This driver can also be built as a module. If so, the module will
be called adp1050.
+config SENSORS_ADP1050_REGULATOR
+ bool "Regulator support for ADP1050 and compatibles"
+ depends on SENSORS_ADP1050 && REGULATOR
+ help
+ If you say yes here you get regulator support for Analog Devices
+ LTP8800-1A, LTP8800-4A, and LTP8800-2. LTP8800 is a family of DC/DC
+ µModule regulators that can provide microprocessor power from 54V
+ power distribution architecture.
+
config SENSORS_BEL_PFE
tristate "Bel PFE Compatible Power Supplies"
help
diff --git a/drivers/hwmon/pmbus/adp1050.c b/drivers/hwmon/pmbus/adp1050.c
index ef46c880b168..a73774f8da2d 100644
--- a/drivers/hwmon/pmbus/adp1050.c
+++ b/drivers/hwmon/pmbus/adp1050.c
@@ -11,6 +11,12 @@
#include "pmbus.h"
+#if IS_ENABLED(CONFIG_SENSORS_ADP1050_REGULATOR)
+static const struct regulator_desc adp1050_reg_desc[] = {
+ PMBUS_REGULATOR_ONE("vout"),
+};
+#endif /* CONFIG_SENSORS_ADP1050_REGULATOR */
+
static struct pmbus_driver_info adp1050_info = {
.pages = 1,
.format[PSC_VOLTAGE_IN] = linear,
@@ -23,19 +29,79 @@ static struct pmbus_driver_info adp1050_info = {
| PMBUS_HAVE_STATUS_TEMP,
};
+static struct pmbus_driver_info adp1051_info = {
+ .pages = 1,
+ .format[PSC_VOLTAGE_IN] = linear,
+ .format[PSC_VOLTAGE_OUT] = linear,
+ .format[PSC_CURRENT_IN] = linear,
+ .format[PSC_TEMPERATURE] = linear,
+ .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN
+ | PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT
+ | PMBUS_HAVE_TEMP
+ | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT
+ | PMBUS_HAVE_STATUS_INPUT
+ | PMBUS_HAVE_STATUS_TEMP,
+};
+
+static struct pmbus_driver_info adp1055_info = {
+ .pages = 1,
+ .format[PSC_VOLTAGE_IN] = linear,
+ .format[PSC_VOLTAGE_OUT] = linear,
+ .format[PSC_CURRENT_IN] = linear,
+ .format[PSC_TEMPERATURE] = linear,
+ .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN
+ | PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT
+ | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_TEMP3
+ | PMBUS_HAVE_POUT
+ | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT
+ | PMBUS_HAVE_STATUS_INPUT
+ | PMBUS_HAVE_STATUS_TEMP,
+};
+
+static struct pmbus_driver_info ltp8800_info = {
+ .pages = 1,
+ .format[PSC_VOLTAGE_IN] = linear,
+ .format[PSC_VOLTAGE_OUT] = linear,
+ .format[PSC_CURRENT_IN] = linear,
+ .format[PSC_TEMPERATURE] = linear,
+ .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN
+ | PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT
+ | PMBUS_HAVE_TEMP
+ | PMBUS_HAVE_POUT
+ | PMBUS_HAVE_STATUS_VOUT
+ | PMBUS_HAVE_STATUS_INPUT
+ | PMBUS_HAVE_STATUS_TEMP,
+#if IS_ENABLED(CONFIG_SENSORS_ADP1050_REGULATOR)
+ .num_regulators = 1,
+ .reg_desc = adp1050_reg_desc,
+#endif
+};
+
static int adp1050_probe(struct i2c_client *client)
{
- return pmbus_do_probe(client, &adp1050_info);
+ struct pmbus_driver_info *info;
+
+ info = (struct pmbus_driver_info *)i2c_get_match_data(client);
+ if (!info)
+ return -ENODEV;
+
+ return pmbus_do_probe(client, info);
}
static const struct i2c_device_id adp1050_id[] = {
- {"adp1050"},
+ { .name = "adp1050", .driver_data = (kernel_ulong_t)&adp1050_info },
+ { .name = "adp1051", .driver_data = (kernel_ulong_t)&adp1051_info },
+ { .name = "adp1055", .driver_data = (kernel_ulong_t)&adp1055_info },
+ { .name = "ltp8800", .driver_data = (kernel_ulong_t)&ltp8800_info },
{}
};
MODULE_DEVICE_TABLE(i2c, adp1050_id);
static const struct of_device_id adp1050_of_match[] = {
- { .compatible = "adi,adp1050"},
+ { .compatible = "adi,adp1050", .data = &adp1050_info },
+ { .compatible = "adi,adp1051", .data = &adp1051_info },
+ { .compatible = "adi,adp1055", .data = &adp1055_info },
+ { .compatible = "adi,ltp8800", .data = &ltp8800_info },
{}
};
MODULE_DEVICE_TABLE(of, adp1050_of_match);
diff --git a/drivers/hwmon/pmbus/isl68137.c b/drivers/hwmon/pmbus/isl68137.c
index 2af921039309..c52c55d2e7f4 100644
--- a/drivers/hwmon/pmbus/isl68137.c
+++ b/drivers/hwmon/pmbus/isl68137.c
@@ -63,6 +63,7 @@ enum chips {
raa228228,
raa229001,
raa229004,
+ raa229621,
};
enum variants {
@@ -465,6 +466,7 @@ static const struct i2c_device_id raa_dmpvr_id[] = {
{"raa228228", raa_dmpvr2_2rail_nontc},
{"raa229001", raa_dmpvr2_2rail},
{"raa229004", raa_dmpvr2_2rail},
+ {"raa229621", raa_dmpvr2_2rail},
{}
};
@@ -512,6 +514,7 @@ static const struct of_device_id isl68137_of_match[] = {
{ .compatible = "renesas,raa228228", .data = (void *)raa_dmpvr2_2rail_nontc },
{ .compatible = "renesas,raa229001", .data = (void *)raa_dmpvr2_2rail },
{ .compatible = "renesas,raa229004", .data = (void *)raa_dmpvr2_2rail },
+ { .compatible = "renesas,raa229621", .data = (void *)raa_dmpvr2_2rail },
{ },
};
diff --git a/drivers/hwmon/pmbus/tps53679.c b/drivers/hwmon/pmbus/tps53679.c
index 63524dff5e75..ca2bfa25eb04 100644
--- a/drivers/hwmon/pmbus/tps53679.c
+++ b/drivers/hwmon/pmbus/tps53679.c
@@ -16,7 +16,7 @@
#include "pmbus.h"
enum chips {
- tps53647, tps53667, tps53676, tps53679, tps53681, tps53688
+ tps53647, tps53667, tps53676, tps53679, tps53681, tps53685, tps53688
};
#define TPS53647_PAGE_NUM 1
@@ -31,7 +31,8 @@ enum chips {
#define TPS53679_PROT_VR13_5MV 0x07 /* VR13.0 mode, 5-mV DAC */
#define TPS53679_PAGE_NUM 2
-#define TPS53681_DEVICE_ID 0x81
+#define TPS53681_DEVICE_ID "\x81"
+#define TPS53685_DEVICE_ID "TIShP"
#define TPS53681_PMBUS_REVISION 0x33
@@ -86,10 +87,12 @@ static int tps53679_identify_phases(struct i2c_client *client,
}
static int tps53679_identify_chip(struct i2c_client *client,
- u8 revision, u16 id)
+ u8 revision, char *id)
{
u8 buf[I2C_SMBUS_BLOCK_MAX];
int ret;
+ int buf_len;
+ int id_len;
ret = pmbus_read_byte_data(client, 0, PMBUS_REVISION);
if (ret < 0)
@@ -102,8 +105,14 @@ static int tps53679_identify_chip(struct i2c_client *client,
ret = i2c_smbus_read_block_data(client, PMBUS_IC_DEVICE_ID, buf);
if (ret < 0)
return ret;
- if (ret != 1 || buf[0] != id) {
- dev_err(&client->dev, "Unexpected device ID 0x%x\n", buf[0]);
+
+ /* Adjust length if null terminator if present */
+ buf_len = (buf[ret - 1] != '\x00' ? ret : ret - 1);
+
+ id_len = strlen(id);
+
+ if (buf_len != id_len || strncmp(id, buf, id_len)) {
+ dev_err(&client->dev, "Unexpected device ID: %*ph\n", ret, buf);
return -ENODEV;
}
return 0;
@@ -117,7 +126,7 @@ static int tps53679_identify_chip(struct i2c_client *client,
*/
static int tps53679_identify_multiphase(struct i2c_client *client,
struct pmbus_driver_info *info,
- int pmbus_rev, int device_id)
+ int pmbus_rev, char *device_id)
{
int ret;
@@ -138,6 +147,16 @@ static int tps53679_identify(struct i2c_client *client,
return tps53679_identify_mode(client, info);
}
+static int tps53685_identify(struct i2c_client *client,
+ struct pmbus_driver_info *info)
+{
+ info->func[1] |= PMBUS_HAVE_VIN | PMBUS_HAVE_IIN | PMBUS_HAVE_PIN |
+ PMBUS_HAVE_STATUS_INPUT;
+ info->format[PSC_VOLTAGE_OUT] = linear;
+ return tps53679_identify_chip(client, TPS53681_PMBUS_REVISION,
+ TPS53685_DEVICE_ID);
+}
+
static int tps53681_identify(struct i2c_client *client,
struct pmbus_driver_info *info)
{
@@ -263,6 +282,10 @@ static int tps53679_probe(struct i2c_client *client)
info->identify = tps53681_identify;
info->read_word_data = tps53681_read_word_data;
break;
+ case tps53685:
+ info->pages = TPS53679_PAGE_NUM;
+ info->identify = tps53685_identify;
+ break;
default:
return -ENODEV;
}
@@ -277,6 +300,7 @@ static const struct i2c_device_id tps53679_id[] = {
{"tps53676", tps53676},
{"tps53679", tps53679},
{"tps53681", tps53681},
+ {"tps53685", tps53685},
{"tps53688", tps53688},
{}
};
@@ -289,6 +313,7 @@ static const struct of_device_id __maybe_unused tps53679_of_match[] = {
{.compatible = "ti,tps53676", .data = (void *)tps53676},
{.compatible = "ti,tps53679", .data = (void *)tps53679},
{.compatible = "ti,tps53681", .data = (void *)tps53681},
+ {.compatible = "ti,tps53685", .data = (void *)tps53685},
{.compatible = "ti,tps53688", .data = (void *)tps53688},
{}
};
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index 7d7d70afde65..a23edd35c19f 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -1448,7 +1448,8 @@ w83627ehf_do_read_temp(struct w83627ehf_data *data, u32 attr,
return 0;
case hwmon_temp_alarm:
if (channel < 3) {
- int bit[] = { 4, 5, 13 };
+ static const int bit[] = { 4, 5, 13 };
+
*val = (data->alarms >> bit[channel]) & 1;
return 0;
}
@@ -1479,7 +1480,8 @@ w83627ehf_do_read_in(struct w83627ehf_data *data, u32 attr,
return 0;
case hwmon_in_alarm:
if (channel < 10) {
- int bit[] = { 0, 1, 2, 3, 8, 21, 20, 16, 17, 19 };
+ static const int bit[] = { 0, 1, 2, 3, 8, 21, 20, 16, 17, 19 };
+
*val = (data->alarms >> bit[channel]) & 1;
return 0;
}
@@ -1507,7 +1509,8 @@ w83627ehf_do_read_fan(struct w83627ehf_data *data, u32 attr,
return 0;
case hwmon_fan_alarm:
if (channel < 5) {
- int bit[] = { 6, 7, 11, 10, 23 };
+ static const int bit[] = { 6, 7, 11, 10, 23 };
+
*val = (data->alarms >> bit[channel]) & 1;
return 0;
}
diff --git a/include/linux/platform_data/emc2305.h b/include/linux/platform_data/emc2305.h
index 54d672dd6f7d..76043a97f975 100644
--- a/include/linux/platform_data/emc2305.h
+++ b/include/linux/platform_data/emc2305.h
@@ -9,14 +9,20 @@
* struct emc2305_platform_data - EMC2305 driver platform data
* @max_state: maximum cooling state of the cooling device;
* @pwm_num: number of active channels;
+ * @pwm_output_mask: PWM output mask
+ * @pwm_polarity_mask: PWM polarity mask
* @pwm_separate: separate PWM settings for every channel;
* @pwm_min: array of minimum PWM per channel;
+ * @pwm_freq: array of PWM frequency per channel
*/
struct emc2305_platform_data {
u8 max_state;
u8 pwm_num;
+ u8 pwm_output_mask;
+ u8 pwm_polarity_mask;
bool pwm_separate;
u8 pwm_min[EMC2305_PWM_MAX];
+ u16 pwm_freq[EMC2305_PWM_MAX];
};
#endif