mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-04 20:19:47 +08:00
hwmon updates for v6.17
* 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 * Various other minor fixes and improvements -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEiHPvMQj9QTOCiqgVyx8mb86fmYEFAmiLiv4ACgkQyx8mb86f mYHCpxAAjHqk1OraRteQoUp0xT8YqSxDCvW8BSCvHSotGKdk5t2Ad9C0rqTqtKzT s0jo1h/dIqVfe1c7siOnAZEoqEVmbUfWJhxMSpMsDCSysJ8lEfP/ofWn4L2GxAyt v60cv9hNZbyeFxCXEe9XFFG2I39kKY1isj8gPiS7HHzDp5PAdSZTjhyV03NgWJJ0 L+aJ9sw5TKMWG6hs4OgkbeAllg2G5oXbZ9AOXhBE71DAIub8lxk+UyJHOng6ecBe I7eAwFKLscOtEd1xzt0FBlHM/0OHj+A+yGwjHVhwXkKgNIN53t/OLLjADTbuVv51 1nW9IAOJHtQ4OzD3MTnQEL+BIC37JbDlPX7VnhHTgYGwJhM5Pj5yUtHLqTlURUfH rZiLhjyGLWKIMGShVXzbKxcyVscMouLTnfn4ZXDjlDzPXOgz5Ha9+Fs3Gd+QP17D Y/w7pIQMA3A0f1FOxlLyRayjcPElb9vmNF2cacxPeqN2EJYRn+8tfYC6290sKBt1 HrCeAVdXLbGCvPFBdC8w8derjQOvkPi+6a07PtUR7BB+QjO23R6FeuzpOFMBucV+ c1q/F2d1gOP2gvtYTz5H2OvLhAKe/FnSEWlVB28C3pTrmpBs+3AkvDSBlSvZ3sIn vLGCVBrSI3SqxwOCnGPwGw4fxbdSrKO9OwRGOjWXxdgNOPDRWog= =6w+m -----END PGP SIGNATURE----- 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 ...
This commit is contained in:
commit
be413ec746
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -25,6 +25,7 @@ description: |
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- maxim,max20710
|
||||
- maxim,max20730
|
||||
- maxim,max20734
|
||||
- maxim,max20743
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -56,6 +56,7 @@ properties:
|
||||
- renesas,raa228228
|
||||
- renesas,raa229001
|
||||
- renesas,raa229004
|
||||
- renesas,raa229621
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -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
|
||||
|
@ -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: |
|
||||
|
@ -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
|
||||
|
@ -18,7 +18,9 @@ description: |
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: ti,lm87
|
||||
enum:
|
||||
- adi,adm1024
|
||||
- ti,lm87
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
================= ========================================
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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'
|
||||
|
@ -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");
|
||||
|
||||
ret = fwnode_property_read_u32_array(fwnode, "pwms", args, ARRAY_SIZE(args));
|
||||
if (n_vals != 3 && n_vals != 4)
|
||||
return -EOVERFLOW;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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[] = {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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]);
|
||||
|
@ -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);
|
||||
|
@ -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) ||
|
||||
|
@ -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, ®val);
|
||||
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, ®val);
|
||||
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, ®val);
|
||||
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, ®val);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (data->config->has_20bit_voltage_current) {
|
||||
err = ina238_read_field_s20(data->client, INA238_CURRENT, ®val);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
err = regmap_read(data->regmap, INA238_CURRENT, ®val);
|
||||
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, ®val);
|
||||
@ -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, ®val);
|
||||
@ -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 },
|
||||
@ -758,6 +850,10 @@ static const struct i2c_device_id ina238_id[] = {
|
||||
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
|
||||
|
@ -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 = <c4282_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,
|
||||
<c2947_chip_info,
|
||||
<c4282_chip_info,
|
||||
ltc4282_groups);
|
||||
if (IS_ERR(hwmon))
|
||||
return PTR_ERR(hwmon);
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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)<p8800_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 = <p8800_info },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, adp1050_of_match);
|
||||
|
@ -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 },
|
||||
{ },
|
||||
};
|
||||
|
||||
|
@ -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},
|
||||
{}
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user