hwmon updates for v6.14-rc1
* New drivers - PMBus client driver for Intel CRPS185 power supply - PMBus client driver for Texas Instruments TPS25990 * Chip support added to existing drivers - pmbus/max15301: Add support for MAX15303 - pmbus/adm1275: Add adm1273 support - lm75: Add NXP P3T1755 support; with it, add I3C support to the driver - asus-ec-sensors: Add TUF GAMING X670E PLUS * Other notable changes - nct6683: Add customer IDs for several MSI and ASRock boards - tmp108: Add regulator support - Improve write protect support in PMBus core - pmbus/dps920ab: Add ability to instantiate through i2c - The hwmon core now accepts NULL as device name parameter to [devm_]hwmon_device_register_with_info ans uses the parent device name as fallback in that case - The PMBus core now provides the PMBUs revision in a debugfs file - asus-ec-sensors: Support for optional CPU fan on AMD 600 motherboards - raspberrypi: Add PM suspend/resume support - dell-smm: Enable manual fan control support on Dell XPS 9370 - pwm-fan: Default to maximum cooling level if provided * Various other minor fixes and improvements -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEiHPvMQj9QTOCiqgVyx8mb86fmYEFAmeOX+AACgkQyx8mb86f mYG4bA/+PJ4hkttSuwK6eR4F1o5l2VQhWPkWn2XzruEJGixhKLJKxKVkUCymmSsd hepHZnw+aUKUmVeb0StSReshp6oGeOHHlKXUM1zv95HI1NMxMrflzeRuqjVNUnDK ZitZkOb2WuUWhZIKIu82ole+3tw/0QyAYmSa9FPyp63rQ7C/QAWl2g4h6m3VdDLZ 1ZOimR/OOFAesZMOuEIBMIHnIqzKLr2QEFd5cZVKM5JbpB7LAHah3fPOvRC3sKco 02OOzFOrtZrXIIPDpsnznm6DF8jgbiKjGb8frR6DLAm/uGvPhuXuS0tYnWHAZs5D nJHDCud1XROK2r9NHDiMZGxCxGOXmB+Fx71jUvY9692NMD2XWUzrqqoOs+c97eeG YszAe1FL9QpgbLJnsFWurU72uvOMmkIeETZUE2cmkupwH+Ja5sc4sDPwf6S8Pwus Y0ZonVqsLQb4UasGcfvFUEb8P6LQdshWx5IWxhfDs+xBo+n5pOEtu+ZCF5Z18k6A A6g4SWWu8QtZOD9fEW0Rt/d9/QtPCTQc8UrJpCofWyKWpLzuoU0Xcs9g/ajLK3Vz +YxM5Pgj7XMWtvPVx2ntnr5VAVKWCUv/jchWuKYKrGI58g3laPagmJMVEy8wrW9+ MpUGzaNDEMlvv7n4Jr4ipkYv9ltOIheu8pmzuI2PcadvAcKmF28= =/7Qs -----END PGP SIGNATURE----- Merge tag 'hwmon-for-v6.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging Pull hwmon updates from Guenter Roeck: "New drivers: - PMBus client driver for Intel CRPS185 power supply - PMBus client driver for Texas Instruments TPS25990 Chip support added to existing drivers: - pmbus/max15301: Add support for MAX15303 - pmbus/adm1275: Add adm1273 support - lm75: Add NXP P3T1755 support; with it, add I3C support to the driver - asus-ec-sensors: Add TUF GAMING X670E PLUS Other notable changes: - nct6683: Add customer IDs for several MSI and ASRock boards - tmp108: Add regulator support - Improve write protect support in PMBus core - pmbus/dps920ab: Add ability to instantiate through i2c - The hwmon core now accepts NULL as device name parameter to [devm_]hwmon_device_register_with_info ans uses the parent device name as fallback in that case - The PMBus core now provides the PMBUs revision in a debugfs file - asus-ec-sensors: Support for optional CPU fan on AMD 600 motherboards - raspberrypi: Add PM suspend/resume support - dell-smm: Enable manual fan control support on Dell XPS 9370 - pwm-fan: Default to maximum cooling level if provided And various other minor fixes and improvements" * tag 'hwmon-for-v6.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (44 commits) hwmon: pmbus: dps920ab: Add ability to instantiate through i2c hwmon: (pwm-fan) Default to the Maximum cooling level if provided hwmon: (asus_atk0110) Use str_enabled_disabled() and str_enable_disable() helpers hwmon: Fix help text for aspeed-g6-pwm-tach hwmon: (dell-smm) Add Dell XPS 9370 to fan control whitelist hwmon: (acpi_power_meter) Fix update the power trip points on failure hwmon: (acpi_power_meter) Fix uninitialized variables hwmon: (core) Use device name as a fallback in devm_hwmon_device_register_with_info hwmon: (pmbus/max15301) Add support for MAX15303 hwmon: (pmbus/adm1275) add adm1273 support dt-bindings: hwmon: adm1275: add adm1273 hwmon: (nct6683) Add another customer ID for MSI hwmon: (pwm-fan): Make use of device properties everywhere hwmon: (lm75) add I3C support for P3T1755 hwmon: (lm75) separate probe into common and I2C parts hwmon: (lm75) Remove superfluous 'client' member from private struct hwmon: (lm75) simplify regulator handling hwmon: (lm75) simplify lm75_write_config() hwmon: (lm75) Hide register size differences in regmap access functions hwmon: (pmbus/crps) Add Intel CRPS185 power supply ...
This commit is contained in:
commit
a4910ed25d
41 changed files with 1378 additions and 268 deletions
|
@ -24,6 +24,7 @@ properties:
|
|||
enum:
|
||||
- adi,adm1075
|
||||
- adi,adm1272
|
||||
- adi,adm1273
|
||||
- adi,adm1275
|
||||
- adi,adm1276
|
||||
- adi,adm1278
|
||||
|
@ -79,6 +80,7 @@ allOf:
|
|||
contains:
|
||||
enum:
|
||||
- adi,adm1272
|
||||
- adi,adm1273
|
||||
then:
|
||||
properties:
|
||||
adi,volt-curr-sample-average:
|
||||
|
|
|
@ -28,6 +28,7 @@ properties:
|
|||
- maxim,max31725
|
||||
- maxim,max31726
|
||||
- maxim,mcp980x
|
||||
- nxp,p3t1755
|
||||
- nxp,pct2075
|
||||
- st,stds75
|
||||
- st,stlm75
|
||||
|
|
|
@ -149,6 +149,8 @@ properties:
|
|||
- injoinic,ip5209
|
||||
# Inspur Power System power supply unit version 1
|
||||
- inspur,ipsps1
|
||||
# Intel common redudant power supply crps185
|
||||
- intel,crps185
|
||||
# Intersil ISL29028 Ambient Light and Proximity Sensor
|
||||
- isil,isl29028
|
||||
# Intersil ISL29030 Ambient Light and Proximity Sensor
|
||||
|
|
|
@ -19,6 +19,14 @@ Supported chips:
|
|||
|
||||
Datasheet: www.analog.com/static/imported-files/data_sheets/ADM1272.pdf
|
||||
|
||||
* Analog Devices ADM1273
|
||||
|
||||
Prefix: 'adm1273'
|
||||
|
||||
Addresses scanned: -
|
||||
|
||||
Datasheet: Not yet publicly available
|
||||
|
||||
* Analog Devices ADM1275
|
||||
|
||||
Prefix: 'adm1275'
|
||||
|
@ -66,14 +74,14 @@ Description
|
|||
-----------
|
||||
|
||||
This driver supports hardware monitoring for Analog Devices ADM1075, ADM1272,
|
||||
ADM1275, ADM1276, ADM1278, ADM1281, ADM1293, and ADM1294 Hot-Swap Controller and
|
||||
Digital Power Monitors.
|
||||
ADM1273, ADM1275, ADM1276, ADM1278, ADM1281, ADM1293, and ADM1294 Hot-Swap
|
||||
Controller and Digital Power Monitors.
|
||||
|
||||
ADM1075, ADM1272, ADM1275, ADM1276, ADM1278, ADM1281, ADM1293, and ADM1294 are hot-swap
|
||||
controllers that allow a circuit board to be removed from or inserted into
|
||||
a live backplane. They also feature current and voltage readback via an
|
||||
integrated 12 bit analog-to-digital converter (ADC), accessed using a
|
||||
PMBus interface.
|
||||
ADM1075, ADM1272, ADM1273, ADM1275, ADM1276, ADM1278, ADM1281, ADM1293, and
|
||||
ADM1294 are hot-swap controllers that allow a circuit board to be removed from
|
||||
or inserted into a live backplane. They also feature current and voltage
|
||||
readback via an integrated 12 bit analog-to-digital converter (ADC), accessed
|
||||
using a PMBus interface.
|
||||
|
||||
The driver is a client driver to the core PMBus driver. Please see
|
||||
Documentation/hwmon/pmbus.rst for details on PMBus client drivers.
|
||||
|
@ -141,7 +149,7 @@ power1_input_highest Highest observed input power.
|
|||
power1_reset_history Write any value to reset history.
|
||||
|
||||
Power attributes are supported on ADM1075, ADM1272,
|
||||
ADM1276, ADM1293, and ADM1294.
|
||||
ADM1273, ADM1276, ADM1293, and ADM1294.
|
||||
|
||||
temp1_input Chip temperature.
|
||||
temp1_max Maximum chip temperature.
|
||||
|
@ -151,6 +159,6 @@ temp1_crit_alarm Critical temperature high alarm.
|
|||
temp1_highest Highest observed temperature.
|
||||
temp1_reset_history Write any value to reset history.
|
||||
|
||||
Temperature attributes are supported on ADM1272 and
|
||||
ADM1278, and ADM1281.
|
||||
Temperature attributes are supported on ADM1272,
|
||||
ADM1273, ADM1278, and ADM1281.
|
||||
======================= =======================================================
|
||||
|
|
|
@ -29,6 +29,7 @@ Supported boards:
|
|||
* ROG STRIX Z690-A GAMING WIFI D4
|
||||
* ROG ZENITH II EXTREME
|
||||
* ROG ZENITH II EXTREME ALPHA
|
||||
* TUF GAMING X670E PLUS
|
||||
|
||||
Authors:
|
||||
- Eugene Shalygin <eugene.shalygin@gmail.com>
|
||||
|
|
97
Documentation/hwmon/crps.rst
Normal file
97
Documentation/hwmon/crps.rst
Normal file
|
@ -0,0 +1,97 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
Kernel driver crps
|
||||
==================
|
||||
|
||||
Supported chips:
|
||||
|
||||
* Intel CRPS185
|
||||
|
||||
Prefix: 'crps185'
|
||||
|
||||
Addresses scanned: -
|
||||
|
||||
Datasheet: Only available under NDA.
|
||||
|
||||
Authors:
|
||||
Ninad Palsule <ninad@linux.ibm.com>
|
||||
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
This driver implements support for Intel Common Redundant Power supply with
|
||||
PMBus support.
|
||||
|
||||
The driver is a client driver to the core PMBus driver.
|
||||
Please see Documentation/hwmon/pmbus.rst for details on PMBus client drivers.
|
||||
|
||||
|
||||
Usage Notes
|
||||
-----------
|
||||
|
||||
This driver does not auto-detect devices. You will have to instantiate the
|
||||
devices explicitly. Please see Documentation/i2c/instantiating-devices.rst for
|
||||
details.
|
||||
|
||||
|
||||
Sysfs entries
|
||||
-------------
|
||||
|
||||
======================= ======================================================
|
||||
curr1_label "iin"
|
||||
curr1_input Measured input current
|
||||
curr1_max Maximum input current
|
||||
curr1_max_alarm Input maximum current high alarm
|
||||
curr1_crit Critial high input current
|
||||
curr1_crit_alarm Input critical current high alarm
|
||||
curr1_rated_max Maximum rated input current
|
||||
|
||||
curr2_label "iout1"
|
||||
curr2_input Measured output current
|
||||
curr2_max Maximum output current
|
||||
curr2_max_alarm Output maximum current high alarm
|
||||
curr2_crit Critial high output current
|
||||
curr2_crit_alarm Output critical current high alarm
|
||||
curr2_rated_max Maximum rated output current
|
||||
|
||||
in1_label "vin"
|
||||
in1_input Measured input voltage
|
||||
in1_crit Critical input over voltage
|
||||
in1_crit_alarm Critical input over voltage alarm
|
||||
in1_max Maximum input over voltage
|
||||
in1_max_alarm Maximum input over voltage alarm
|
||||
in1_rated_min Minimum rated input voltage
|
||||
in1_rated_max Maximum rated input voltage
|
||||
|
||||
in2_label "vout1"
|
||||
in2_input Measured input voltage
|
||||
in2_crit Critical input over voltage
|
||||
in2_crit_alarm Critical input over voltage alarm
|
||||
in2_lcrit Critical input under voltage fault
|
||||
in2_lcrit_alarm Critical input under voltage fault alarm
|
||||
in2_max Maximum input over voltage
|
||||
in2_max_alarm Maximum input over voltage alarm
|
||||
in2_min Minimum input under voltage warning
|
||||
in2_min_alarm Minimum input under voltage warning alarm
|
||||
in2_rated_min Minimum rated input voltage
|
||||
in2_rated_max Maximum rated input voltage
|
||||
|
||||
power1_label "pin"
|
||||
power1_input Measured input power
|
||||
power1_alarm Input power high alarm
|
||||
power1_max Maximum input power
|
||||
power1_rated_max Maximum rated input power
|
||||
|
||||
temp[1-2]_input Measured temperature
|
||||
temp[1-2]_crit Critical temperature
|
||||
temp[1-2]_crit_alarm Critical temperature alarm
|
||||
temp[1-2]_max Maximum temperature
|
||||
temp[1-2]_max_alarm Maximum temperature alarm
|
||||
temp[1-2]_rated_max Maximum rated temperature
|
||||
|
||||
fan1_alarm Fan 1 warning.
|
||||
fan1_fault Fan 1 fault.
|
||||
fan1_input Fan 1 speed in RPM.
|
||||
fan1_target Fan 1 target.
|
||||
======================= ======================================================
|
|
@ -64,7 +64,8 @@ hwmon_device_register_with_info.
|
|||
|
||||
All supported hwmon device registration functions only accept valid device
|
||||
names. Device names including invalid characters (whitespace, '*', or '-')
|
||||
will be rejected. The 'name' parameter is mandatory.
|
||||
will be rejected. If NULL is passed as name parameter, the hardware monitoring
|
||||
device name will be derived from the parent device name.
|
||||
|
||||
If the driver doesn't use a static device name (for example it uses
|
||||
dev_name()), and therefore cannot make sure the name only contains valid
|
||||
|
|
|
@ -58,6 +58,7 @@ Hardware Monitoring Kernel Drivers
|
|||
corsair-cpro
|
||||
corsair-psu
|
||||
cros_ec_hwmon
|
||||
crps
|
||||
da9052
|
||||
da9055
|
||||
dell-smm-hwmon
|
||||
|
@ -237,6 +238,7 @@ Hardware Monitoring Kernel Drivers
|
|||
tmp464
|
||||
tmp513
|
||||
tps23861
|
||||
tps25990
|
||||
tps40422
|
||||
tps53679
|
||||
tps546d24
|
||||
|
|
|
@ -33,7 +33,7 @@ details.
|
|||
|
||||
The shunt value in micro-ohms, shunt voltage range and averaging can be set
|
||||
with device properties.
|
||||
Please refer to the Documentation/devicetree/bindings/hwmon/isl,isl28022.yaml
|
||||
Please refer to the Documentation/devicetree/bindings/hwmon/renesas,isl28022.yaml
|
||||
for bindings if the device tree is used.
|
||||
|
||||
The driver supports only shunt and bus continuous ADC mode at 15bit resolution.
|
||||
|
@ -48,6 +48,7 @@ The following attributes are supported. All attributes are read-only.
|
|||
|
||||
======================= =======================================================
|
||||
in0_input bus voltage (milli Volt)
|
||||
in1_input shunt voltage (milli Volt)
|
||||
|
||||
curr1_input current (milli Ampere)
|
||||
power1_input power (micro Watt)
|
||||
|
|
|
@ -121,15 +121,17 @@ Supported chips:
|
|||
|
||||
https://www.ti.com/product/TMP1075
|
||||
|
||||
* NXP LM75B, PCT2075
|
||||
* NXP LM75B, P3T1755, PCT2075
|
||||
|
||||
Prefix: 'lm75b', 'pct2075'
|
||||
Prefix: 'lm75b', 'p3t1755', 'pct2075'
|
||||
|
||||
Addresses scanned: none
|
||||
|
||||
Datasheet: Publicly available at the NXP website
|
||||
|
||||
https://www.nxp.com/documents/data_sheet/LM75B.pdf
|
||||
https://www.nxp.com/docs/en/data-sheet/LM75B.pdf
|
||||
|
||||
https://www.nxp.com/docs/en/data-sheet/P3T1755.pdf
|
||||
|
||||
https://www.nxp.com/docs/en/data-sheet/PCT2075.pdf
|
||||
|
||||
|
|
|
@ -13,6 +13,14 @@ Supported chips:
|
|||
|
||||
Datasheet: https://datasheets.maximintegrated.com/en/ds/MAX15301.pdf
|
||||
|
||||
* Maxim MAX15303
|
||||
|
||||
Prefix: 'max15303'
|
||||
|
||||
Addresses scanned: -
|
||||
|
||||
Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/max15303.pdf
|
||||
|
||||
Author: Erik Rosen <erik.rosen@metormote.com>
|
||||
|
||||
|
||||
|
|
|
@ -55,14 +55,16 @@ Tested Boards and Firmware Versions
|
|||
The driver has been reported to work with the following boards and
|
||||
firmware versions.
|
||||
|
||||
=============== ===============================================
|
||||
Board Firmware version
|
||||
=============== ===============================================
|
||||
Intel DH87RL NCT6683D EC firmware version 1.0 build 04/03/13
|
||||
Intel DH87MC NCT6683D EC firmware version 1.0 build 04/03/13
|
||||
Intel DB85FL NCT6683D EC firmware version 1.0 build 04/03/13
|
||||
ASRock X570 NCT6683D EC firmware version 1.0 build 06/28/19
|
||||
ASRock X670E NCT6686D EC firmware version 1.0 build 05/19/22
|
||||
MSI B550 NCT6687D EC firmware version 1.0 build 05/07/20
|
||||
MSI X670-P NCT6687D EC firmware version 0.0 build 09/27/22
|
||||
=============== ===============================================
|
||||
=============================== ===============================================
|
||||
Board Firmware version
|
||||
=============================== ===============================================
|
||||
Intel DH87RL NCT6683D EC firmware version 1.0 build 04/03/13
|
||||
Intel DH87MC NCT6683D EC firmware version 1.0 build 04/03/13
|
||||
Intel DB85FL NCT6683D EC firmware version 1.0 build 04/03/13
|
||||
ASRock X570 NCT6683D EC firmware version 1.0 build 06/28/19
|
||||
ASRock X670E NCT6686D EC firmware version 1.0 build 05/19/22
|
||||
ASRock B650 Steel Legend WiFi NCT6686D EC firmware version 1.0 build 11/09/23
|
||||
MSI B550 NCT6687D EC firmware version 1.0 build 05/07/20
|
||||
MSI X670-P NCT6687D EC firmware version 0.0 build 09/27/22
|
||||
MSI X870E NCT6687D EC firmware version 0.0 build 11/13/24
|
||||
=============================== ===============================================
|
||||
|
|
|
@ -312,6 +312,10 @@ currently provides a flags field with four bits used::
|
|||
|
||||
#define PMBUS_USE_COEFFICIENTS_CMD BIT(5)
|
||||
|
||||
#define PMBUS_OP_PROTECTED BIT(6)
|
||||
|
||||
#define PMBUS_VOUT_PROTECTED BIT(7)
|
||||
|
||||
struct pmbus_platform_data {
|
||||
u32 flags; /* Device specific flags */
|
||||
|
||||
|
@ -373,3 +377,34 @@ PMBUS_USE_COEFFICIENTS_CMD
|
|||
|
||||
When this flag is set the PMBus core driver will use the COEFFICIENTS
|
||||
register to initialize the coefficients for the direct mode format.
|
||||
|
||||
PMBUS_OP_PROTECTED
|
||||
|
||||
Set if the chip OPERATION command is protected and protection is not
|
||||
determined by the standard WRITE_PROTECT command.
|
||||
|
||||
PMBUS_VOUT_PROTECTED
|
||||
|
||||
Set if the chip VOUT_COMMAND command is protected and protection is not
|
||||
determined by the standard WRITE_PROTECT command.
|
||||
|
||||
Module parameter
|
||||
----------------
|
||||
|
||||
pmbus_core.wp: PMBus write protect forced mode
|
||||
|
||||
PMBus may come up with a variety of write protection configuration.
|
||||
'pmbus_core.wp' may be used if a particular write protection is necessary.
|
||||
The ability to actually alter the protection may also depend on the chip
|
||||
so the actual runtime write protection configuration may differ from
|
||||
the requested one. pmbus_core currently support the following value:
|
||||
|
||||
* 0: write protection removed.
|
||||
* 1: Disable all writes except to the WRITE_PROTECT, OPERATION,
|
||||
PAGE, ON_OFF_CONFIG and VOUT_COMMAND commands.
|
||||
* 2: Disable all writes except to the WRITE_PROTECT, OPERATION and
|
||||
PAGE commands.
|
||||
* 3: Disable all writes except to the WRITE_PROTECT command. Note that
|
||||
protection should include the PAGE register. This may be problematic
|
||||
for multi-page chips, if the chips strictly follows the PMBus
|
||||
specification, preventing the chip from changing the active page.
|
||||
|
|
147
Documentation/hwmon/tps25990.rst
Normal file
147
Documentation/hwmon/tps25990.rst
Normal file
|
@ -0,0 +1,147 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
Kernel driver tps25990
|
||||
======================
|
||||
|
||||
Supported chips:
|
||||
|
||||
* TI TPS25990
|
||||
|
||||
Prefix: 'tps25990'
|
||||
|
||||
* Datasheet
|
||||
|
||||
Publicly available at Texas Instruments website: https://www.ti.com/lit/gpn/tps25990
|
||||
|
||||
Author:
|
||||
|
||||
Jerome Brunet <jbrunet@baylibre.com>
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
This driver implements support for TI TPS25990 eFuse.
|
||||
This is an integrated, high-current circuit protection and power
|
||||
management device with PMBUS interface
|
||||
|
||||
Device compliant with:
|
||||
|
||||
- PMBus rev 1.3 interface.
|
||||
|
||||
Device supports direct format for reading input voltages,
|
||||
output voltage, input current, input power and temperature.
|
||||
|
||||
Due to the specificities of the chip, all history reset attributes
|
||||
are tied together. Resetting the history of a sensor, resets the
|
||||
history of all the sensors.
|
||||
|
||||
The driver exports the following attributes via the 'sysfs' files
|
||||
for input current:
|
||||
|
||||
**curr1_average**
|
||||
|
||||
**curr1_crit**
|
||||
|
||||
**curr1_crit_alarm**
|
||||
|
||||
**curr1_highest**
|
||||
|
||||
**curr1_input**
|
||||
|
||||
**curr1_label**
|
||||
|
||||
**curr1_max**
|
||||
|
||||
**curr1_max_alarm**
|
||||
|
||||
**curr1_reset_history**
|
||||
|
||||
The driver provides the following attributes for main input voltage:
|
||||
|
||||
**in1_average**
|
||||
|
||||
**in1_crit**
|
||||
|
||||
**in1_crit_alarm**
|
||||
|
||||
**in1_highest**
|
||||
|
||||
**in1_input**
|
||||
|
||||
**in1_label**
|
||||
|
||||
**in1_lcrit**
|
||||
|
||||
**in1_lcrit_alarm**
|
||||
|
||||
**in1_lowest**
|
||||
|
||||
**in1_max**
|
||||
|
||||
**in1_max_alarm**
|
||||
|
||||
**in1_min**
|
||||
|
||||
**in1_min_alarm**
|
||||
|
||||
**in1_reset_history**
|
||||
|
||||
The driver provides the following attributes for auxiliary input voltage:
|
||||
|
||||
**in2_input**
|
||||
|
||||
**in2_label**
|
||||
|
||||
The driver provides the following attributes for output voltage:
|
||||
|
||||
**in3_average**
|
||||
|
||||
**in3_input**
|
||||
|
||||
**in3_label**
|
||||
|
||||
**in3_lowest**
|
||||
|
||||
**in3_min**
|
||||
|
||||
**in3_min_alarm**
|
||||
|
||||
**in3_reset_history**
|
||||
|
||||
The driver provides the following attributes for input power:
|
||||
|
||||
**power1_alarm**
|
||||
|
||||
**power1_average**
|
||||
|
||||
**power1_input**
|
||||
|
||||
**power1_input_highest**
|
||||
|
||||
**power1_label**
|
||||
|
||||
**power1_max**
|
||||
|
||||
**power1_reset_history**
|
||||
|
||||
The driver provides the following attributes for temperature:
|
||||
|
||||
**temp1_average**
|
||||
|
||||
**temp1_crit**
|
||||
|
||||
**temp1_crit_alarm**
|
||||
|
||||
**temp1_highest**
|
||||
|
||||
**temp1_input**
|
||||
|
||||
**temp1_max**
|
||||
|
||||
**temp1_max_alarm**
|
||||
|
||||
**temp1_reset_history**
|
||||
|
||||
The driver provides the following attributes for sampling:
|
||||
|
||||
**samples**
|
11
MAINTAINERS
11
MAINTAINERS
|
@ -1252,7 +1252,7 @@ S: Maintained
|
|||
F: Documentation/devicetree/bindings/rtc/amlogic,a4-rtc.yaml
|
||||
F: drivers/rtc/rtc-amlogic-a4.c
|
||||
|
||||
AMPHENOL CHIPCAP 2 HUMIDITY-TEMPERATURE IIO DRIVER
|
||||
AMPHENOL CHIPCAP 2 DRIVER
|
||||
M: Javier Carrasco <javier.carrasco.cruz@gmail.com>
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
|
@ -6098,6 +6098,13 @@ L: linux-input@vger.kernel.org
|
|||
S: Maintained
|
||||
F: drivers/hid/hid-creative-sb0540.c
|
||||
|
||||
INTEL CRPS COMMON REDUNDANT PSU DRIVER
|
||||
M: Ninad Palsule <ninad@linux.ibm.com>
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/crps.rst
|
||||
F: drivers/hwmon/pmbus/crps.c
|
||||
|
||||
CRYPTO API
|
||||
M: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
M: "David S. Miller" <davem@davemloft.net>
|
||||
|
@ -23284,6 +23291,8 @@ M: Jerome Brunet <jbrunet@baylibre.com>
|
|||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/hwmon/pmbus/ti,tps25990.yaml
|
||||
F: Documentation/hwmon/tps25990.rst
|
||||
F: drivers/hwmon/pmbus/tps25990.c
|
||||
|
||||
TEXAS INSTRUMENTS TPS23861 PoE PSE DRIVER
|
||||
M: Robert Marko <robert.marko@sartura.hr>
|
||||
|
|
|
@ -413,7 +413,7 @@ config SENSORS_ASPEED
|
|||
will be called aspeed_pwm_tacho.
|
||||
|
||||
config SENSORS_ASPEED_G6
|
||||
tristate "ASPEED g6 PWM and Fan tach driver"
|
||||
tristate "ASPEED G6 PWM and Fan tach driver"
|
||||
depends on ARCH_ASPEED || COMPILE_TEST
|
||||
depends on PWM
|
||||
help
|
||||
|
@ -421,7 +421,7 @@ config SENSORS_ASPEED_G6
|
|||
controllers.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called aspeed_pwm_tacho.
|
||||
will be called aspeed_g6_pwm_tach.
|
||||
|
||||
config SENSORS_ATXP1
|
||||
tristate "Attansic ATXP1 VID controller"
|
||||
|
@ -1412,7 +1412,9 @@ config SENSORS_LM73
|
|||
config SENSORS_LM75
|
||||
tristate "National Semiconductor LM75 and compatibles"
|
||||
depends on I2C
|
||||
depends on I3C || !I3C
|
||||
select REGMAP_I2C
|
||||
select REGMAP_I3C if I3C
|
||||
help
|
||||
If you say yes here you get support for one common type of
|
||||
temperature sensor chip, with models including:
|
||||
|
|
|
@ -84,6 +84,7 @@ struct acpi_power_meter_resource {
|
|||
u64 power;
|
||||
u64 cap;
|
||||
u64 avg_interval;
|
||||
bool power_alarm;
|
||||
int sensors_valid;
|
||||
unsigned long sensors_last_updated;
|
||||
struct sensor_device_attribute sensors[NUM_SENSORS];
|
||||
|
@ -292,8 +293,8 @@ static ssize_t set_trip(struct device *dev, struct device_attribute *devattr,
|
|||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct acpi_device *acpi_dev = to_acpi_device(dev);
|
||||
struct acpi_power_meter_resource *resource = acpi_dev->driver_data;
|
||||
unsigned long temp, trip_bk;
|
||||
int res;
|
||||
unsigned long temp;
|
||||
|
||||
res = kstrtoul(buf, 10, &temp);
|
||||
if (res)
|
||||
|
@ -301,13 +302,15 @@ static ssize_t set_trip(struct device *dev, struct device_attribute *devattr,
|
|||
|
||||
temp = DIV_ROUND_CLOSEST(temp, 1000);
|
||||
|
||||
mutex_lock(&resource->lock);
|
||||
guard(mutex)(&resource->lock);
|
||||
|
||||
trip_bk = resource->trip[attr->index - 7];
|
||||
resource->trip[attr->index - 7] = temp;
|
||||
res = set_acpi_trip(resource);
|
||||
mutex_unlock(&resource->lock);
|
||||
|
||||
if (res)
|
||||
if (res) {
|
||||
resource->trip[attr->index - 7] = trip_bk;
|
||||
return res;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
@ -396,6 +399,9 @@ static ssize_t show_val(struct device *dev,
|
|||
struct acpi_device *acpi_dev = to_acpi_device(dev);
|
||||
struct acpi_power_meter_resource *resource = acpi_dev->driver_data;
|
||||
u64 val = 0;
|
||||
int ret;
|
||||
|
||||
guard(mutex)(&resource->lock);
|
||||
|
||||
switch (attr->index) {
|
||||
case 0:
|
||||
|
@ -423,10 +429,17 @@ static ssize_t show_val(struct device *dev,
|
|||
val = 0;
|
||||
break;
|
||||
case 6:
|
||||
if (resource->power > resource->cap)
|
||||
val = 1;
|
||||
else
|
||||
val = 0;
|
||||
ret = update_meter(resource);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* need to update cap if not to support the notification. */
|
||||
if (!(resource->caps.flags & POWER_METER_CAN_NOTIFY)) {
|
||||
ret = update_cap(resource);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
val = resource->power_alarm || resource->power > resource->cap;
|
||||
resource->power_alarm = resource->power > resource->cap;
|
||||
break;
|
||||
case 7:
|
||||
case 8:
|
||||
|
@ -847,12 +860,20 @@ static void acpi_power_meter_notify(struct acpi_device *device, u32 event)
|
|||
sysfs_notify(&device->dev.kobj, NULL, POWER_AVERAGE_NAME);
|
||||
break;
|
||||
case METER_NOTIFY_CAP:
|
||||
mutex_lock(&resource->lock);
|
||||
res = update_cap(resource);
|
||||
if (res)
|
||||
dev_err_once(&device->dev, "update cap failed when capping value is changed.\n");
|
||||
mutex_unlock(&resource->lock);
|
||||
sysfs_notify(&device->dev.kobj, NULL, POWER_CAP_NAME);
|
||||
break;
|
||||
case METER_NOTIFY_INTERVAL:
|
||||
sysfs_notify(&device->dev.kobj, NULL, POWER_AVG_INTERVAL_NAME);
|
||||
break;
|
||||
case METER_NOTIFY_CAPPING:
|
||||
mutex_lock(&resource->lock);
|
||||
resource->power_alarm = true;
|
||||
mutex_unlock(&resource->lock);
|
||||
sysfs_notify(&device->dev.kobj, NULL, POWER_ALARM_NAME);
|
||||
dev_info(&device->dev, "Capping in progress.\n");
|
||||
break;
|
||||
|
|
|
@ -250,6 +250,8 @@ static const struct ec_sensor_info sensors_family_amd_600[] = {
|
|||
EC_SENSOR("Water_In", hwmon_temp, 1, 0x01, 0x00),
|
||||
[ec_sensor_temp_water_out] =
|
||||
EC_SENSOR("Water_Out", hwmon_temp, 1, 0x01, 0x01),
|
||||
[ec_sensor_fan_cpu_opt] =
|
||||
EC_SENSOR("CPU_Opt", hwmon_fan, 2, 0x00, 0xb0),
|
||||
};
|
||||
|
||||
static const struct ec_sensor_info sensors_family_intel_300[] = {
|
||||
|
@ -477,6 +479,15 @@ static const struct ec_board_info board_info_zenith_ii_extreme = {
|
|||
.family = family_amd_500_series,
|
||||
};
|
||||
|
||||
static const struct ec_board_info board_info_tuf_gaming_x670e_plus = {
|
||||
.sensors = SENSOR_TEMP_CPU | SENSOR_TEMP_CPU_PACKAGE |
|
||||
SENSOR_TEMP_MB | SENSOR_TEMP_VRM |
|
||||
SENSOR_TEMP_WATER_IN | SENSOR_TEMP_WATER_OUT |
|
||||
SENSOR_FAN_CPU_OPT,
|
||||
.mutex_path = ACPI_GLOBAL_LOCK_PSEUDO_PATH,
|
||||
.family = family_amd_600_series,
|
||||
};
|
||||
|
||||
#define DMI_EXACT_MATCH_ASUS_BOARD_NAME(name, board_info) \
|
||||
{ \
|
||||
.matches = { \
|
||||
|
@ -538,6 +549,8 @@ static const struct dmi_system_id dmi_table[] = {
|
|||
&board_info_zenith_ii_extreme),
|
||||
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG ZENITH II EXTREME ALPHA",
|
||||
&board_info_zenith_ii_extreme),
|
||||
DMI_EXACT_MATCH_ASUS_BOARD_NAME("TUF GAMING X670E-PLUS",
|
||||
&board_info_tuf_gaming_x670e_plus),
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <linux/jiffies.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/string_choices.h>
|
||||
|
||||
#define ATK_HID "ATK0110"
|
||||
|
||||
|
@ -441,7 +442,7 @@ static void atk_print_sensor(struct atk_data *data, union acpi_object *obj)
|
|||
flags->integer.value,
|
||||
name->string.pointer,
|
||||
limit1->integer.value, limit2->integer.value,
|
||||
enable->integer.value ? "enabled" : "disabled");
|
||||
str_enabled_disabled(enable->integer.value));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1074,8 +1075,7 @@ static int atk_ec_enabled(struct atk_data *data)
|
|||
err = -EIO;
|
||||
} else {
|
||||
err = (buf->value != 0);
|
||||
dev_dbg(dev, "EC is %sabled\n",
|
||||
err ? "en" : "dis");
|
||||
dev_dbg(dev, "EC is %s\n", str_enabled_disabled(err));
|
||||
}
|
||||
|
||||
ACPI_FREE(obj);
|
||||
|
@ -1096,18 +1096,15 @@ static int atk_ec_ctl(struct atk_data *data, int enable)
|
|||
|
||||
obj = atk_sitm(data, &sitm);
|
||||
if (IS_ERR(obj)) {
|
||||
dev_err(dev, "Failed to %sable the EC\n",
|
||||
enable ? "en" : "dis");
|
||||
dev_err(dev, "Failed to %s the EC\n", str_enable_disable(enable));
|
||||
return PTR_ERR(obj);
|
||||
}
|
||||
ec_ret = (struct atk_acpi_ret_buffer *)obj->buffer.pointer;
|
||||
if (ec_ret->flags == 0) {
|
||||
dev_err(dev, "Failed to %sable the EC\n",
|
||||
enable ? "en" : "dis");
|
||||
dev_err(dev, "Failed to %s the EC\n", str_enable_disable(enable));
|
||||
err = -EIO;
|
||||
} else {
|
||||
dev_info(dev, "EC %sabled\n",
|
||||
enable ? "en" : "dis");
|
||||
dev_info(dev, "EC %s\n", str_enabled_disabled(enable));
|
||||
}
|
||||
|
||||
ACPI_FREE(obj);
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/hwmon.h>
|
||||
|
@ -556,55 +557,40 @@ static int cc2_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
|
|||
int channel, long *val)
|
||||
{
|
||||
struct cc2_data *data = dev_get_drvdata(dev);
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&data->dev_access_lock);
|
||||
guard(mutex)(&data->dev_access_lock);
|
||||
|
||||
switch (type) {
|
||||
case hwmon_temp:
|
||||
ret = cc2_measurement(data, type, val);
|
||||
break;
|
||||
return cc2_measurement(data, type, val);
|
||||
case hwmon_humidity:
|
||||
switch (attr) {
|
||||
case hwmon_humidity_input:
|
||||
ret = cc2_measurement(data, type, val);
|
||||
break;
|
||||
return cc2_measurement(data, type, val);
|
||||
case hwmon_humidity_min:
|
||||
ret = cc2_get_reg_val(data, CC2_R_ALARM_L_ON, val);
|
||||
break;
|
||||
return cc2_get_reg_val(data, CC2_R_ALARM_L_ON, val);
|
||||
case hwmon_humidity_min_hyst:
|
||||
ret = cc2_get_reg_val(data, CC2_R_ALARM_L_OFF, val);
|
||||
break;
|
||||
return cc2_get_reg_val(data, CC2_R_ALARM_L_OFF, val);
|
||||
case hwmon_humidity_max:
|
||||
ret = cc2_get_reg_val(data, CC2_R_ALARM_H_ON, val);
|
||||
break;
|
||||
return cc2_get_reg_val(data, CC2_R_ALARM_H_ON, val);
|
||||
case hwmon_humidity_max_hyst:
|
||||
ret = cc2_get_reg_val(data, CC2_R_ALARM_H_OFF, val);
|
||||
break;
|
||||
return cc2_get_reg_val(data, CC2_R_ALARM_H_OFF, val);
|
||||
case hwmon_humidity_min_alarm:
|
||||
ret = cc2_humidity_min_alarm_status(data, val);
|
||||
break;
|
||||
return cc2_humidity_min_alarm_status(data, val);
|
||||
case hwmon_humidity_max_alarm:
|
||||
ret = cc2_humidity_max_alarm_status(data, val);
|
||||
break;
|
||||
return cc2_humidity_max_alarm_status(data, val);
|
||||
default:
|
||||
ret = -EOPNOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = -EOPNOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->dev_access_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cc2_write(struct device *dev, enum hwmon_sensor_types type, u32 attr,
|
||||
int channel, long val)
|
||||
{
|
||||
struct cc2_data *data = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
u16 arg;
|
||||
u8 cmd;
|
||||
|
||||
|
@ -614,41 +600,28 @@ static int cc2_write(struct device *dev, enum hwmon_sensor_types type, u32 attr,
|
|||
if (val < 0 || val > CC2_RH_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&data->dev_access_lock);
|
||||
guard(mutex)(&data->dev_access_lock);
|
||||
|
||||
switch (attr) {
|
||||
case hwmon_humidity_min:
|
||||
cmd = CC2_W_ALARM_L_ON;
|
||||
arg = cc2_rh_to_reg(val);
|
||||
ret = cc2_write_reg(data, cmd, arg);
|
||||
break;
|
||||
|
||||
return cc2_write_reg(data, cmd, arg);
|
||||
case hwmon_humidity_min_hyst:
|
||||
cmd = CC2_W_ALARM_L_OFF;
|
||||
arg = cc2_rh_to_reg(val);
|
||||
ret = cc2_write_reg(data, cmd, arg);
|
||||
break;
|
||||
|
||||
return cc2_write_reg(data, cmd, arg);
|
||||
case hwmon_humidity_max:
|
||||
cmd = CC2_W_ALARM_H_ON;
|
||||
arg = cc2_rh_to_reg(val);
|
||||
ret = cc2_write_reg(data, cmd, arg);
|
||||
break;
|
||||
|
||||
return cc2_write_reg(data, cmd, arg);
|
||||
case hwmon_humidity_max_hyst:
|
||||
cmd = CC2_W_ALARM_H_OFF;
|
||||
arg = cc2_rh_to_reg(val);
|
||||
ret = cc2_write_reg(data, cmd, arg);
|
||||
break;
|
||||
|
||||
return cc2_write_reg(data, cmd, arg);
|
||||
default:
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->dev_access_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cc2_request_ready_irq(struct cc2_data *data, struct device *dev)
|
||||
|
|
|
@ -1544,6 +1544,14 @@ static const struct dmi_system_id i8k_whitelist_fan_control[] __initconst = {
|
|||
},
|
||||
.driver_data = (void *)&i8k_fan_control_data[I8K_FAN_34A3_35A3],
|
||||
},
|
||||
{
|
||||
.ident = "Dell XPS 13 9370",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "XPS 13 9370"),
|
||||
},
|
||||
.driver_data = (void *)&i8k_fan_control_data[I8K_FAN_30A3_31A3],
|
||||
},
|
||||
{
|
||||
.ident = "Dell Optiplex 7000",
|
||||
.matches = {
|
||||
|
|
|
@ -158,11 +158,6 @@ static umode_t hwmon_is_visible(const struct hwmon_ops *ops,
|
|||
|
||||
/* Thermal zone handling */
|
||||
|
||||
/*
|
||||
* The complex conditional is necessary to avoid a cyclic dependency
|
||||
* between hwmon and thermal_sys modules.
|
||||
*/
|
||||
#ifdef CONFIG_THERMAL_OF
|
||||
static int hwmon_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
|
||||
{
|
||||
struct hwmon_thermal_data *tdata = thermal_zone_device_priv(tz);
|
||||
|
@ -268,6 +263,9 @@ static int hwmon_thermal_register_sensors(struct device *dev)
|
|||
void *drvdata = dev_get_drvdata(dev);
|
||||
int i;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_THERMAL_OF))
|
||||
return 0;
|
||||
|
||||
for (i = 1; info[i]; i++) {
|
||||
int j;
|
||||
|
||||
|
@ -296,6 +294,9 @@ static void hwmon_thermal_notify(struct device *dev, int index)
|
|||
struct hwmon_device *hwdev = to_hwmon_device(dev);
|
||||
struct hwmon_thermal_data *tzdata;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_THERMAL_OF))
|
||||
return;
|
||||
|
||||
list_for_each_entry(tzdata, &hwdev->tzdata, node) {
|
||||
if (tzdata->index == index) {
|
||||
thermal_zone_device_update(tzdata->tzd,
|
||||
|
@ -304,16 +305,6 @@ static void hwmon_thermal_notify(struct device *dev, int index)
|
|||
}
|
||||
}
|
||||
|
||||
#else
|
||||
static int hwmon_thermal_register_sensors(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hwmon_thermal_notify(struct device *dev, int index) { }
|
||||
|
||||
#endif /* IS_REACHABLE(CONFIG_THERMAL) && ... */
|
||||
|
||||
static int hwmon_attr_base(enum hwmon_sensor_types type)
|
||||
{
|
||||
if (type == hwmon_in || type == hwmon_intrusion)
|
||||
|
@ -1179,6 +1170,12 @@ devm_hwmon_device_register_with_info(struct device *dev, const char *name,
|
|||
if (!dev)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (!name) {
|
||||
name = devm_hwmon_sanitize_name(dev, dev_name(dev));
|
||||
if (IS_ERR(name))
|
||||
return ERR_CAST(name);
|
||||
}
|
||||
|
||||
ptr = devres_alloc(devm_hwmon_release, sizeof(*ptr), GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
|
|
@ -486,7 +486,7 @@ static int isl28022_probe(struct i2c_client *client)
|
|||
}
|
||||
|
||||
static const struct i2c_device_id isl28022_ids[] = {
|
||||
{ "isl28022", 0},
|
||||
{ "isl28022" },
|
||||
{ /* LIST END */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, isl28022_ids);
|
||||
|
@ -506,8 +506,7 @@ static struct i2c_driver isl28022_driver = {
|
|||
.id_table = isl28022_ids,
|
||||
};
|
||||
|
||||
static int __init
|
||||
isl28022_init(void)
|
||||
static int __init isl28022_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
@ -519,15 +518,13 @@ isl28022_init(void)
|
|||
debugfs_remove_recursive(isl28022_debugfs_root);
|
||||
return err;
|
||||
}
|
||||
module_init(isl28022_init);
|
||||
|
||||
static void __exit
|
||||
isl28022_exit(void)
|
||||
static void __exit isl28022_exit(void)
|
||||
{
|
||||
i2c_del_driver(&isl28022_driver);
|
||||
debugfs_remove_recursive(isl28022_debugfs_root);
|
||||
}
|
||||
|
||||
module_init(isl28022_init);
|
||||
module_exit(isl28022_exit);
|
||||
|
||||
MODULE_AUTHOR("Carsten Spieß <mail@carsten-spiess.de>");
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i3c/device.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/of.h>
|
||||
|
@ -38,6 +39,7 @@ enum lm75_type { /* keep sorted in alphabetical order */
|
|||
max6626,
|
||||
max31725,
|
||||
mcp980x,
|
||||
p3t1755,
|
||||
pct2075,
|
||||
stds75,
|
||||
stlm75,
|
||||
|
@ -104,17 +106,15 @@ static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
|
|||
#define LM75_REG_MAX 0x03
|
||||
#define PCT2075_REG_IDLE 0x04
|
||||
|
||||
/* Each client has this additional data */
|
||||
struct lm75_data {
|
||||
struct i2c_client *client;
|
||||
struct regmap *regmap;
|
||||
struct regulator *vs;
|
||||
u16 orig_conf;
|
||||
u16 current_conf;
|
||||
u8 resolution; /* In bits, 9 to 16 */
|
||||
unsigned int sample_time; /* In ms */
|
||||
enum lm75_type kind;
|
||||
const struct lm75_params *params;
|
||||
u8 reg_buf[1];
|
||||
u8 val_buf[3];
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
@ -222,6 +222,13 @@ static const struct lm75_params device_params[] = {
|
|||
.default_resolution = 9,
|
||||
.default_sample_time = MSEC_PER_SEC / 18,
|
||||
},
|
||||
[p3t1755] = {
|
||||
.clr_mask = 1 << 1 | 1 << 7, /* disable SMBAlert and one-shot */
|
||||
.default_resolution = 12,
|
||||
.default_sample_time = 55,
|
||||
.num_sample_times = 4,
|
||||
.sample_times = (unsigned int []){ 28, 55, 110, 220 },
|
||||
},
|
||||
[pct2075] = {
|
||||
.default_resolution = 11,
|
||||
.default_sample_time = MSEC_PER_SEC / 10,
|
||||
|
@ -276,6 +283,7 @@ static const struct lm75_params device_params[] = {
|
|||
.default_sample_time = 125,
|
||||
.num_sample_times = 4,
|
||||
.sample_times = (unsigned int []){ 125, 250, 1000, 4000 },
|
||||
.alarm = true,
|
||||
},
|
||||
[tmp175] = {
|
||||
.set_mask = 3 << 5, /* 12-bit mode */
|
||||
|
@ -332,41 +340,11 @@ static inline long lm75_reg_to_mc(s16 temp, u8 resolution)
|
|||
return ((temp >> (16 - resolution)) * 1000) >> (resolution - 8);
|
||||
}
|
||||
|
||||
static int lm75_write_config(struct lm75_data *data, u16 set_mask,
|
||||
u16 clr_mask)
|
||||
static inline int lm75_write_config(struct lm75_data *data, u16 set_mask,
|
||||
u16 clr_mask)
|
||||
{
|
||||
unsigned int value;
|
||||
|
||||
clr_mask |= LM75_SHUTDOWN << (8 * data->params->config_reg_16bits);
|
||||
value = data->current_conf & ~clr_mask;
|
||||
value |= set_mask;
|
||||
|
||||
if (data->current_conf != value) {
|
||||
s32 err;
|
||||
if (data->params->config_reg_16bits)
|
||||
err = regmap_write(data->regmap, LM75_REG_CONF, value);
|
||||
else
|
||||
err = i2c_smbus_write_byte_data(data->client,
|
||||
LM75_REG_CONF,
|
||||
value);
|
||||
if (err)
|
||||
return err;
|
||||
data->current_conf = value;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lm75_read_config(struct lm75_data *data)
|
||||
{
|
||||
int ret;
|
||||
unsigned int status;
|
||||
|
||||
if (data->params->config_reg_16bits) {
|
||||
ret = regmap_read(data->regmap, LM75_REG_CONF, &status);
|
||||
return ret ? ret : status;
|
||||
}
|
||||
|
||||
return i2c_smbus_read_byte_data(data->client, LM75_REG_CONF);
|
||||
return regmap_update_bits(data->regmap, LM75_REG_CONF,
|
||||
clr_mask | LM75_SHUTDOWN, set_mask);
|
||||
}
|
||||
|
||||
static irqreturn_t lm75_alarm_handler(int irq, void *private)
|
||||
|
@ -418,7 +396,8 @@ static int lm75_read(struct device *dev, enum hwmon_sensor_types type,
|
|||
if (attr == hwmon_temp_alarm) {
|
||||
switch (data->kind) {
|
||||
case as6200:
|
||||
*val = (regval >> 5) & 0x1;
|
||||
case tmp112:
|
||||
*val = (regval >> 13) & 0x1;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
@ -469,7 +448,6 @@ static int lm75_write_temp(struct device *dev, u32 attr, long temp)
|
|||
static int lm75_update_interval(struct device *dev, long val)
|
||||
{
|
||||
struct lm75_data *data = dev_get_drvdata(dev);
|
||||
unsigned int reg;
|
||||
u8 index;
|
||||
s32 err;
|
||||
|
||||
|
@ -489,19 +467,14 @@ static int lm75_update_interval(struct device *dev, long val)
|
|||
break;
|
||||
case tmp112:
|
||||
case as6200:
|
||||
err = regmap_read(data->regmap, LM75_REG_CONF, ®);
|
||||
if (err < 0)
|
||||
return err;
|
||||
reg &= ~0x00c0;
|
||||
reg |= (3 - index) << 6;
|
||||
err = regmap_write(data->regmap, LM75_REG_CONF, reg);
|
||||
err = regmap_update_bits(data->regmap, LM75_REG_CONF,
|
||||
0xc000, (3 - index) << 14);
|
||||
if (err < 0)
|
||||
return err;
|
||||
data->sample_time = data->params->sample_times[index];
|
||||
break;
|
||||
case pct2075:
|
||||
err = i2c_smbus_write_byte_data(data->client, PCT2075_REG_IDLE,
|
||||
index + 1);
|
||||
err = regmap_write(data->regmap, PCT2075_REG_IDLE, index + 1);
|
||||
if (err)
|
||||
return err;
|
||||
data->sample_time = data->params->sample_times[index];
|
||||
|
@ -598,6 +571,115 @@ static bool lm75_is_volatile_reg(struct device *dev, unsigned int reg)
|
|||
return reg == LM75_REG_TEMP || reg == LM75_REG_CONF;
|
||||
}
|
||||
|
||||
static int lm75_i2c_reg_read(void *context, unsigned int reg, unsigned int *val)
|
||||
{
|
||||
struct i2c_client *client = context;
|
||||
struct lm75_data *data = i2c_get_clientdata(client);
|
||||
int ret;
|
||||
|
||||
if (reg == LM75_REG_CONF) {
|
||||
if (!data->params->config_reg_16bits)
|
||||
ret = i2c_smbus_read_byte_data(client, LM75_REG_CONF);
|
||||
else
|
||||
ret = i2c_smbus_read_word_data(client, LM75_REG_CONF);
|
||||
} else {
|
||||
ret = i2c_smbus_read_word_swapped(client, reg);
|
||||
}
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*val = ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lm75_i2c_reg_write(void *context, unsigned int reg, unsigned int val)
|
||||
{
|
||||
struct i2c_client *client = context;
|
||||
struct lm75_data *data = i2c_get_clientdata(client);
|
||||
|
||||
if (reg == PCT2075_REG_IDLE ||
|
||||
(reg == LM75_REG_CONF && !data->params->config_reg_16bits))
|
||||
return i2c_smbus_write_byte_data(client, reg, val);
|
||||
else if (reg == LM75_REG_CONF)
|
||||
return i2c_smbus_write_word_data(client, reg, val);
|
||||
return i2c_smbus_write_word_swapped(client, reg, val);
|
||||
}
|
||||
|
||||
static const struct regmap_bus lm75_i2c_regmap_bus = {
|
||||
.reg_read = lm75_i2c_reg_read,
|
||||
.reg_write = lm75_i2c_reg_write,
|
||||
};
|
||||
|
||||
static int lm75_i3c_reg_read(void *context, unsigned int reg, unsigned int *val)
|
||||
{
|
||||
struct i3c_device *i3cdev = context;
|
||||
struct lm75_data *data = i3cdev_get_drvdata(i3cdev);
|
||||
struct i3c_priv_xfer xfers[] = {
|
||||
{
|
||||
.rnw = false,
|
||||
.len = 1,
|
||||
.data.out = data->reg_buf,
|
||||
},
|
||||
{
|
||||
.rnw = true,
|
||||
.len = 2,
|
||||
.data.out = data->val_buf,
|
||||
},
|
||||
};
|
||||
int ret;
|
||||
|
||||
data->reg_buf[0] = reg;
|
||||
|
||||
if (reg == LM75_REG_CONF && !data->params->config_reg_16bits)
|
||||
xfers[1].len--;
|
||||
|
||||
ret = i3c_device_do_priv_xfers(i3cdev, xfers, 2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (reg == LM75_REG_CONF && !data->params->config_reg_16bits)
|
||||
*val = data->val_buf[0];
|
||||
else if (reg == LM75_REG_CONF)
|
||||
*val = data->val_buf[0] | (data->val_buf[1] << 8);
|
||||
else
|
||||
*val = data->val_buf[1] | (data->val_buf[0] << 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lm75_i3c_reg_write(void *context, unsigned int reg, unsigned int val)
|
||||
{
|
||||
struct i3c_device *i3cdev = context;
|
||||
struct lm75_data *data = i3cdev_get_drvdata(i3cdev);
|
||||
struct i3c_priv_xfer xfers[] = {
|
||||
{
|
||||
.rnw = false,
|
||||
.len = 3,
|
||||
.data.out = data->val_buf,
|
||||
},
|
||||
};
|
||||
|
||||
data->val_buf[0] = reg;
|
||||
|
||||
if (reg == PCT2075_REG_IDLE ||
|
||||
(reg == LM75_REG_CONF && !data->params->config_reg_16bits)) {
|
||||
xfers[0].len--;
|
||||
data->val_buf[1] = val & 0xff;
|
||||
} else if (reg == LM75_REG_CONF) {
|
||||
data->val_buf[1] = val & 0xff;
|
||||
data->val_buf[2] = (val >> 8) & 0xff;
|
||||
} else {
|
||||
data->val_buf[1] = (val >> 8) & 0xff;
|
||||
data->val_buf[2] = val & 0xff;
|
||||
}
|
||||
|
||||
return i3c_device_do_priv_xfers(i3cdev, xfers, 1);
|
||||
}
|
||||
|
||||
static const struct regmap_bus lm75_i3c_regmap_bus = {
|
||||
.reg_read = lm75_i3c_reg_read,
|
||||
.reg_write = lm75_i3c_reg_write,
|
||||
};
|
||||
|
||||
static const struct regmap_config lm75_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 16,
|
||||
|
@ -610,46 +692,33 @@ static const struct regmap_config lm75_regmap_config = {
|
|||
.use_single_write = true,
|
||||
};
|
||||
|
||||
static void lm75_disable_regulator(void *data)
|
||||
{
|
||||
struct lm75_data *lm75 = data;
|
||||
|
||||
regulator_disable(lm75->vs);
|
||||
}
|
||||
|
||||
static void lm75_remove(void *data)
|
||||
{
|
||||
struct lm75_data *lm75 = data;
|
||||
struct i2c_client *client = lm75->client;
|
||||
|
||||
i2c_smbus_write_byte_data(client, LM75_REG_CONF, lm75->orig_conf);
|
||||
regmap_write(lm75->regmap, LM75_REG_CONF, lm75->orig_conf);
|
||||
}
|
||||
|
||||
static int lm75_probe(struct i2c_client *client)
|
||||
static int lm75_generic_probe(struct device *dev, const char *name,
|
||||
enum lm75_type kind, int irq, struct regmap *regmap)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct device *hwmon_dev;
|
||||
struct lm75_data *data;
|
||||
int status, err;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
|
||||
return -EIO;
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(struct lm75_data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->client = client;
|
||||
data->kind = (uintptr_t)i2c_get_match_data(client);
|
||||
/* needed by custom regmap callbacks */
|
||||
dev_set_drvdata(dev, data);
|
||||
|
||||
data->vs = devm_regulator_get(dev, "vs");
|
||||
if (IS_ERR(data->vs))
|
||||
return PTR_ERR(data->vs);
|
||||
data->kind = kind;
|
||||
data->regmap = regmap;
|
||||
|
||||
data->regmap = devm_regmap_init_i2c(client, &lm75_regmap_config);
|
||||
if (IS_ERR(data->regmap))
|
||||
return PTR_ERR(data->regmap);
|
||||
err = devm_regulator_get_enable(dev, "vs");
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Set to LM75 resolution (9 bits, 1/2 degree C) and range.
|
||||
* Then tweak to be more precise when appropriate.
|
||||
|
@ -661,25 +730,11 @@ static int lm75_probe(struct i2c_client *client)
|
|||
data->sample_time = data->params->default_sample_time;
|
||||
data->resolution = data->params->default_resolution;
|
||||
|
||||
/* Enable the power */
|
||||
err = regulator_enable(data->vs);
|
||||
if (err) {
|
||||
dev_err(dev, "failed to enable regulator: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = devm_add_action_or_reset(dev, lm75_disable_regulator, data);
|
||||
/* Cache original configuration */
|
||||
err = regmap_read(data->regmap, LM75_REG_CONF, &status);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Cache original configuration */
|
||||
status = lm75_read_config(data);
|
||||
if (status < 0) {
|
||||
dev_dbg(dev, "Can't read config? %d\n", status);
|
||||
return status;
|
||||
}
|
||||
data->orig_conf = status;
|
||||
data->current_conf = status;
|
||||
|
||||
err = lm75_write_config(data, data->params->set_mask,
|
||||
data->params->clr_mask);
|
||||
|
@ -690,20 +745,19 @@ static int lm75_probe(struct i2c_client *client)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
|
||||
data, &lm75_chip_info,
|
||||
NULL);
|
||||
hwmon_dev = devm_hwmon_device_register_with_info(dev, name, data,
|
||||
&lm75_chip_info, NULL);
|
||||
if (IS_ERR(hwmon_dev))
|
||||
return PTR_ERR(hwmon_dev);
|
||||
|
||||
if (client->irq) {
|
||||
if (irq) {
|
||||
if (data->params->alarm) {
|
||||
err = devm_request_threaded_irq(dev,
|
||||
client->irq,
|
||||
irq,
|
||||
NULL,
|
||||
&lm75_alarm_handler,
|
||||
IRQF_ONESHOT,
|
||||
client->name,
|
||||
name,
|
||||
hwmon_dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -713,12 +767,29 @@ static int lm75_probe(struct i2c_client *client)
|
|||
}
|
||||
}
|
||||
|
||||
dev_info(dev, "%s: sensor '%s'\n", dev_name(hwmon_dev), client->name);
|
||||
dev_info(dev, "%s: sensor '%s'\n", dev_name(hwmon_dev), name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id lm75_ids[] = {
|
||||
static int lm75_i2c_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct regmap *regmap;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
regmap = devm_regmap_init(dev, &lm75_i2c_regmap_bus, client, &lm75_regmap_config);
|
||||
if (IS_ERR(regmap))
|
||||
return PTR_ERR(regmap);
|
||||
|
||||
return lm75_generic_probe(dev, client->name, (uintptr_t)i2c_get_match_data(client),
|
||||
client->irq, regmap);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id lm75_i2c_ids[] = {
|
||||
{ "adt75", adt75, },
|
||||
{ "as6200", as6200, },
|
||||
{ "at30ts74", at30ts74, },
|
||||
|
@ -734,6 +805,7 @@ static const struct i2c_device_id lm75_ids[] = {
|
|||
{ "max31725", max31725, },
|
||||
{ "max31726", max31725, },
|
||||
{ "mcp980x", mcp980x, },
|
||||
{ "p3t1755", p3t1755, },
|
||||
{ "pct2075", pct2075, },
|
||||
{ "stds75", stds75, },
|
||||
{ "stlm75", stlm75, },
|
||||
|
@ -750,7 +822,38 @@ static const struct i2c_device_id lm75_ids[] = {
|
|||
{ "tmp1075", tmp1075, },
|
||||
{ /* LIST END */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, lm75_ids);
|
||||
MODULE_DEVICE_TABLE(i2c, lm75_i2c_ids);
|
||||
|
||||
struct lm75_i3c_device {
|
||||
enum lm75_type type;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
static const struct lm75_i3c_device lm75_i3c_p3t1755 = {
|
||||
.name = "p3t1755",
|
||||
.type = p3t1755,
|
||||
};
|
||||
|
||||
static const struct i3c_device_id lm75_i3c_ids[] = {
|
||||
I3C_DEVICE(0x011b, 0x152a, &lm75_i3c_p3t1755),
|
||||
{ /* LIST END */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i3c, lm75_i3c_ids);
|
||||
|
||||
static int lm75_i3c_probe(struct i3c_device *i3cdev)
|
||||
{
|
||||
struct device *dev = i3cdev_to_dev(i3cdev);
|
||||
const struct lm75_i3c_device *id_data;
|
||||
struct regmap *regmap;
|
||||
|
||||
regmap = devm_regmap_init(dev, &lm75_i3c_regmap_bus, i3cdev, &lm75_regmap_config);
|
||||
if (IS_ERR(regmap))
|
||||
return PTR_ERR(regmap);
|
||||
|
||||
id_data = i3c_device_match_id(i3cdev, lm75_i3c_ids)->data;
|
||||
|
||||
return lm75_generic_probe(dev, id_data->name, id_data->type, 0, regmap);
|
||||
}
|
||||
|
||||
static const struct of_device_id __maybe_unused lm75_of_match[] = {
|
||||
{
|
||||
|
@ -813,6 +916,10 @@ static const struct of_device_id __maybe_unused lm75_of_match[] = {
|
|||
.compatible = "maxim,mcp980x",
|
||||
.data = (void *)mcp980x
|
||||
},
|
||||
{
|
||||
.compatible = "nxp,p3t1755",
|
||||
.data = (void *)p3t1755
|
||||
},
|
||||
{
|
||||
.compatible = "nxp,pct2075",
|
||||
.data = (void *)pct2075
|
||||
|
@ -972,32 +1079,16 @@ static int lm75_detect(struct i2c_client *new_client,
|
|||
#ifdef CONFIG_PM
|
||||
static int lm75_suspend(struct device *dev)
|
||||
{
|
||||
int status;
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct lm75_data *data = dev_get_drvdata(dev);
|
||||
|
||||
status = i2c_smbus_read_byte_data(client, LM75_REG_CONF);
|
||||
if (status < 0) {
|
||||
dev_dbg(&client->dev, "Can't read config? %d\n", status);
|
||||
return status;
|
||||
}
|
||||
status = status | LM75_SHUTDOWN;
|
||||
i2c_smbus_write_byte_data(client, LM75_REG_CONF, status);
|
||||
return 0;
|
||||
return regmap_update_bits(data->regmap, LM75_REG_CONF, LM75_SHUTDOWN, LM75_SHUTDOWN);
|
||||
}
|
||||
|
||||
static int lm75_resume(struct device *dev)
|
||||
{
|
||||
int status;
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct lm75_data *data = dev_get_drvdata(dev);
|
||||
|
||||
status = i2c_smbus_read_byte_data(client, LM75_REG_CONF);
|
||||
if (status < 0) {
|
||||
dev_dbg(&client->dev, "Can't read config? %d\n", status);
|
||||
return status;
|
||||
}
|
||||
status = status & ~LM75_SHUTDOWN;
|
||||
i2c_smbus_write_byte_data(client, LM75_REG_CONF, status);
|
||||
return 0;
|
||||
return regmap_update_bits(data->regmap, LM75_REG_CONF, LM75_SHUTDOWN, 0);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops lm75_dev_pm_ops = {
|
||||
|
@ -1009,20 +1100,28 @@ static const struct dev_pm_ops lm75_dev_pm_ops = {
|
|||
#define LM75_DEV_PM_OPS NULL
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static struct i2c_driver lm75_driver = {
|
||||
static struct i2c_driver lm75_i2c_driver = {
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.driver = {
|
||||
.name = "lm75",
|
||||
.of_match_table = of_match_ptr(lm75_of_match),
|
||||
.pm = LM75_DEV_PM_OPS,
|
||||
},
|
||||
.probe = lm75_probe,
|
||||
.id_table = lm75_ids,
|
||||
.probe = lm75_i2c_probe,
|
||||
.id_table = lm75_i2c_ids,
|
||||
.detect = lm75_detect,
|
||||
.address_list = normal_i2c,
|
||||
};
|
||||
|
||||
module_i2c_driver(lm75_driver);
|
||||
static struct i3c_driver lm75_i3c_driver = {
|
||||
.driver = {
|
||||
.name = "lm75_i3c",
|
||||
},
|
||||
.probe = lm75_i3c_probe,
|
||||
.id_table = lm75_i3c_ids,
|
||||
};
|
||||
|
||||
module_i3c_i2c_driver(lm75_i3c_driver, &lm75_i2c_driver)
|
||||
|
||||
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
|
||||
MODULE_DESCRIPTION("LM75 driver");
|
||||
|
|
|
@ -175,9 +175,11 @@ superio_exit(int ioreg)
|
|||
#define NCT6683_CUSTOMER_ID_MSI 0x201
|
||||
#define NCT6683_CUSTOMER_ID_MSI2 0x200
|
||||
#define NCT6683_CUSTOMER_ID_MSI3 0x207
|
||||
#define NCT6683_CUSTOMER_ID_MSI4 0x20d
|
||||
#define NCT6683_CUSTOMER_ID_ASROCK 0xe2c
|
||||
#define NCT6683_CUSTOMER_ID_ASROCK2 0xe1b
|
||||
#define NCT6683_CUSTOMER_ID_ASROCK3 0x1631
|
||||
#define NCT6683_CUSTOMER_ID_ASROCK4 0x163e
|
||||
|
||||
#define NCT6683_REG_BUILD_YEAR 0x604
|
||||
#define NCT6683_REG_BUILD_MONTH 0x605
|
||||
|
@ -1227,12 +1229,16 @@ static int nct6683_probe(struct platform_device *pdev)
|
|||
break;
|
||||
case NCT6683_CUSTOMER_ID_MSI3:
|
||||
break;
|
||||
case NCT6683_CUSTOMER_ID_MSI4:
|
||||
break;
|
||||
case NCT6683_CUSTOMER_ID_ASROCK:
|
||||
break;
|
||||
case NCT6683_CUSTOMER_ID_ASROCK2:
|
||||
break;
|
||||
case NCT6683_CUSTOMER_ID_ASROCK3:
|
||||
break;
|
||||
case NCT6683_CUSTOMER_ID_ASROCK4:
|
||||
break;
|
||||
default:
|
||||
if (!force)
|
||||
return -ENODEV;
|
||||
|
|
|
@ -42,6 +42,9 @@
|
|||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#undef DEFAULT_SYMBOL_NAMESPACE
|
||||
#define DEFAULT_SYMBOL_NAMESPACE "HWMON_NCT6775"
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -56,9 +59,6 @@
|
|||
#include "lm75.h"
|
||||
#include "nct6775.h"
|
||||
|
||||
#undef DEFAULT_SYMBOL_NAMESPACE
|
||||
#define DEFAULT_SYMBOL_NAMESPACE "HWMON_NCT6775"
|
||||
|
||||
#define USE_ALTERNATE
|
||||
|
||||
/* used to set data->name = nct6775_device_names[data->sio_kind] */
|
||||
|
|
|
@ -30,7 +30,7 @@ struct p9_sbe_occ {
|
|||
#define to_p9_sbe_occ(x) container_of((x), struct p9_sbe_occ, occ)
|
||||
|
||||
static ssize_t ffdc_read(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *battr, char *buf, loff_t pos,
|
||||
const struct bin_attribute *battr, char *buf, loff_t pos,
|
||||
size_t count)
|
||||
{
|
||||
ssize_t rc = 0;
|
||||
|
@ -48,7 +48,7 @@ static ssize_t ffdc_read(struct file *filp, struct kobject *kobj,
|
|||
|
||||
return rc;
|
||||
}
|
||||
static BIN_ATTR_RO(ffdc, OCC_MAX_RESP_WORDS * 4);
|
||||
static const BIN_ATTR_RO(ffdc, OCC_MAX_RESP_WORDS * 4);
|
||||
|
||||
static bool p9_sbe_occ_save_ffdc(struct p9_sbe_occ *ctx, const void *resp,
|
||||
size_t resp_len)
|
||||
|
|
|
@ -51,7 +51,7 @@ config SENSORS_ADM1275
|
|||
tristate "Analog Devices ADM1275 and compatibles"
|
||||
help
|
||||
If you say yes here you get hardware monitoring support for Analog
|
||||
Devices ADM1075, ADM1272, ADM1275, ADM1276, ADM1278, ADM1281,
|
||||
Devices ADM1075, ADM1272, ADM1273, ADM1275, ADM1276, ADM1278, ADM1281,
|
||||
ADM1293, and ADM1294 Hot-Swap Controller and Digital Power Monitors.
|
||||
|
||||
This driver can also be built as a module. If so, the module will
|
||||
|
@ -85,6 +85,15 @@ config SENSORS_BPA_RS600
|
|||
This driver can also be built as a module. If so, the module will
|
||||
be called bpa-rs600.
|
||||
|
||||
config SENSORS_CRPS
|
||||
tristate "Intel Common Redundant Power Supply"
|
||||
help
|
||||
If you say yes here you get hardware monitoring support for the Intel
|
||||
Common Redundant Power Supply.
|
||||
|
||||
This driver can also be built as a module. If so, the module will
|
||||
be called crps.
|
||||
|
||||
config SENSORS_DELTA_AHE50DC_FAN
|
||||
tristate "Delta AHE-50DC fan control module"
|
||||
help
|
||||
|
@ -251,7 +260,7 @@ config SENSORS_MAX15301
|
|||
tristate "Maxim MAX15301"
|
||||
help
|
||||
If you say yes here you get hardware monitoring support for Maxim
|
||||
MAX15301, as well as for Flex BMR461.
|
||||
MAX15301, MAX15303, as well as for Flex BMR461.
|
||||
|
||||
This driver can also be built as a module. If so, the module will
|
||||
be called max15301.
|
||||
|
@ -510,6 +519,23 @@ config SENSORS_TDA38640_REGULATOR
|
|||
If you say yes here you get regulator support for Infineon
|
||||
TDA38640 as regulator.
|
||||
|
||||
config SENSORS_TPS25990
|
||||
tristate "TI TPS25990"
|
||||
help
|
||||
If you say yes here you get hardware monitoring support for TI
|
||||
TPS25990.
|
||||
|
||||
This driver can also be built as a module. If so, the module will
|
||||
be called tps25990.
|
||||
|
||||
config SENSORS_TPS25990_REGULATOR
|
||||
bool "Regulator support for TPS25990 and compatibles"
|
||||
depends on SENSORS_TPS25990 && REGULATOR
|
||||
default SENSORS_TPS25990
|
||||
help
|
||||
If you say yes here you get regulator support for Texas Instruments
|
||||
TPS25990.
|
||||
|
||||
config SENSORS_TPS40422
|
||||
tristate "TI TPS40422"
|
||||
help
|
||||
|
|
|
@ -51,6 +51,7 @@ obj-$(CONFIG_SENSORS_PXE1610) += pxe1610.o
|
|||
obj-$(CONFIG_SENSORS_Q54SJ108A2) += q54sj108a2.o
|
||||
obj-$(CONFIG_SENSORS_STPDDC60) += stpddc60.o
|
||||
obj-$(CONFIG_SENSORS_TDA38640) += tda38640.o
|
||||
obj-$(CONFIG_SENSORS_TPS25990) += tps25990.o
|
||||
obj-$(CONFIG_SENSORS_TPS40422) += tps40422.o
|
||||
obj-$(CONFIG_SENSORS_TPS53679) += tps53679.o
|
||||
obj-$(CONFIG_SENSORS_TPS546D24) += tps546d24.o
|
||||
|
@ -61,3 +62,4 @@ obj-$(CONFIG_SENSORS_XDPE122) += xdpe12284.o
|
|||
obj-$(CONFIG_SENSORS_XDPE152) += xdpe152c4.o
|
||||
obj-$(CONFIG_SENSORS_ZL6100) += zl6100.o
|
||||
obj-$(CONFIG_SENSORS_PIM4328) += pim4328.o
|
||||
obj-$(CONFIG_SENSORS_CRPS) += crps.o
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include <linux/log2.h>
|
||||
#include "pmbus.h"
|
||||
|
||||
enum chips { adm1075, adm1272, adm1275, adm1276, adm1278, adm1281, adm1293, adm1294 };
|
||||
enum chips { adm1075, adm1272, adm1273, adm1275, adm1276, adm1278, adm1281, adm1293, adm1294 };
|
||||
|
||||
#define ADM1275_MFR_STATUS_IOUT_WARN2 BIT(0)
|
||||
#define ADM1293_MFR_STATUS_VAUX_UV_WARN BIT(5)
|
||||
|
@ -479,6 +479,7 @@ static int adm1275_read_byte_data(struct i2c_client *client, int page, int reg)
|
|||
static const struct i2c_device_id adm1275_id[] = {
|
||||
{ "adm1075", adm1075 },
|
||||
{ "adm1272", adm1272 },
|
||||
{ "adm1273", adm1273 },
|
||||
{ "adm1275", adm1275 },
|
||||
{ "adm1276", adm1276 },
|
||||
{ "adm1278", adm1278 },
|
||||
|
@ -555,9 +556,9 @@ static int adm1275_probe(struct i2c_client *client)
|
|||
"Device mismatch: Configured %s, detected %s\n",
|
||||
client->name, mid->name);
|
||||
|
||||
if (mid->driver_data == adm1272 || mid->driver_data == adm1278 ||
|
||||
mid->driver_data == adm1281 || mid->driver_data == adm1293 ||
|
||||
mid->driver_data == adm1294)
|
||||
if (mid->driver_data == adm1272 || mid->driver_data == adm1273 ||
|
||||
mid->driver_data == adm1278 || mid->driver_data == adm1281 ||
|
||||
mid->driver_data == adm1293 || mid->driver_data == adm1294)
|
||||
config_read_fn = i2c_smbus_read_word_data;
|
||||
else
|
||||
config_read_fn = i2c_smbus_read_byte_data;
|
||||
|
@ -630,6 +631,7 @@ static int adm1275_probe(struct i2c_client *client)
|
|||
PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
|
||||
break;
|
||||
case adm1272:
|
||||
case adm1273:
|
||||
data->have_vout = true;
|
||||
data->have_pin_max = true;
|
||||
data->have_temp_max = true;
|
||||
|
|
74
drivers/hwmon/pmbus/crps.c
Normal file
74
drivers/hwmon/pmbus/crps.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright 2024 IBM Corp.
|
||||
*/
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/pmbus.h>
|
||||
|
||||
#include "pmbus.h"
|
||||
|
||||
static const struct i2c_device_id crps_id[] = {
|
||||
{ "intel_crps185" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, crps_id);
|
||||
|
||||
static struct pmbus_driver_info crps_info = {
|
||||
.pages = 1,
|
||||
/* PSU uses default linear data format. */
|
||||
.func[0] = PMBUS_HAVE_PIN | PMBUS_HAVE_IOUT |
|
||||
PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_IIN |
|
||||
PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT |
|
||||
PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
|
||||
PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 |
|
||||
PMBUS_HAVE_STATUS_TEMP |
|
||||
PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12,
|
||||
};
|
||||
|
||||
static int crps_probe(struct i2c_client *client)
|
||||
{
|
||||
int rc;
|
||||
struct device *dev = &client->dev;
|
||||
char buf[I2C_SMBUS_BLOCK_MAX + 2] = { 0 };
|
||||
|
||||
rc = i2c_smbus_read_block_data(client, PMBUS_MFR_MODEL, buf);
|
||||
if (rc < 0)
|
||||
return dev_err_probe(dev, rc, "Failed to read PMBUS_MFR_MODEL\n");
|
||||
|
||||
if (rc != 7 || strncmp(buf, "03NK260", 7)) {
|
||||
buf[rc] = '\0';
|
||||
return dev_err_probe(dev, -ENODEV, "Model '%s' not supported\n", buf);
|
||||
}
|
||||
|
||||
rc = pmbus_do_probe(client, &crps_info);
|
||||
if (rc)
|
||||
return dev_err_probe(dev, rc, "Failed to probe\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id crps_of_match[] = {
|
||||
{
|
||||
.compatible = "intel,crps185",
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, crps_of_match);
|
||||
|
||||
static struct i2c_driver crps_driver = {
|
||||
.driver = {
|
||||
.name = "crps",
|
||||
.of_match_table = crps_of_match,
|
||||
},
|
||||
.probe = crps_probe,
|
||||
.id_table = crps_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(crps_driver);
|
||||
|
||||
MODULE_AUTHOR("Ninad Palsule");
|
||||
MODULE_DESCRIPTION("PMBus driver for Intel Common Redundant power supplies");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_IMPORT_NS("PMBUS");
|
|
@ -190,12 +190,19 @@ static const struct of_device_id __maybe_unused dps920ab_of_match[] = {
|
|||
|
||||
MODULE_DEVICE_TABLE(of, dps920ab_of_match);
|
||||
|
||||
static const struct i2c_device_id dps920ab_device_id[] = {
|
||||
{ "dps920ab" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, dps920ab_device_id);
|
||||
|
||||
static struct i2c_driver dps920ab_driver = {
|
||||
.driver = {
|
||||
.name = "dps920ab",
|
||||
.of_match_table = of_match_ptr(dps920ab_of_match),
|
||||
},
|
||||
.probe = dps920ab_probe,
|
||||
.id_table = dps920ab_device_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(dps920ab_driver);
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
static const struct i2c_device_id max15301_id[] = {
|
||||
{ "bmr461" },
|
||||
{ "max15301" },
|
||||
{ "max15303" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, max15301_id);
|
||||
|
|
|
@ -487,6 +487,8 @@ struct pmbus_driver_info {
|
|||
/* Regulator ops */
|
||||
|
||||
extern const struct regulator_ops pmbus_regulator_ops;
|
||||
int pmbus_regulator_init_cb(struct regulator_dev *rdev,
|
||||
struct regulator_config *config);
|
||||
|
||||
/* Macros for filling in array of struct regulator_desc */
|
||||
#define PMBUS_REGULATOR_STEP(_name, _id, _voltages, _step, _min_uV) \
|
||||
|
@ -501,6 +503,7 @@ extern const struct regulator_ops pmbus_regulator_ops;
|
|||
.n_voltages = _voltages, \
|
||||
.uV_step = _step, \
|
||||
.min_uV = _min_uV, \
|
||||
.init_cb = pmbus_regulator_init_cb, \
|
||||
}
|
||||
|
||||
#define PMBUS_REGULATOR(_name, _id) PMBUS_REGULATOR_STEP(_name, _id, 0, 0, 0)
|
||||
|
@ -516,6 +519,7 @@ extern const struct regulator_ops pmbus_regulator_ops;
|
|||
.n_voltages = _voltages, \
|
||||
.uV_step = _step, \
|
||||
.min_uV = _min_uV, \
|
||||
.init_cb = pmbus_regulator_init_cb, \
|
||||
}
|
||||
|
||||
#define PMBUS_REGULATOR_ONE(_name) PMBUS_REGULATOR_STEP_ONE(_name, 0, 0, 0)
|
||||
|
|
|
@ -31,6 +31,9 @@
|
|||
#define PMBUS_ATTR_ALLOC_SIZE 32
|
||||
#define PMBUS_NAME_SIZE 24
|
||||
|
||||
static int wp = -1;
|
||||
module_param(wp, int, 0444);
|
||||
|
||||
struct pmbus_sensor {
|
||||
struct pmbus_sensor *next;
|
||||
char name[PMBUS_NAME_SIZE]; /* sysfs sensor name */
|
||||
|
@ -2665,6 +2668,56 @@ static void pmbus_remove_pec(void *dev)
|
|||
device_remove_file(dev, &dev_attr_pec);
|
||||
}
|
||||
|
||||
static void pmbus_init_wp(struct i2c_client *client, struct pmbus_data *data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (wp) {
|
||||
case 0:
|
||||
_pmbus_write_byte_data(client, -1,
|
||||
PMBUS_WRITE_PROTECT, 0);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
_pmbus_write_byte_data(client, -1,
|
||||
PMBUS_WRITE_PROTECT, PB_WP_VOUT);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
_pmbus_write_byte_data(client, -1,
|
||||
PMBUS_WRITE_PROTECT, PB_WP_OP);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
_pmbus_write_byte_data(client, -1,
|
||||
PMBUS_WRITE_PROTECT, PB_WP_ALL);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Ignore the other values */
|
||||
break;
|
||||
}
|
||||
|
||||
ret = _pmbus_read_byte_data(client, -1, PMBUS_WRITE_PROTECT);
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
switch (ret & PB_WP_ANY) {
|
||||
case PB_WP_ALL:
|
||||
data->flags |= PMBUS_OP_PROTECTED;
|
||||
fallthrough;
|
||||
case PB_WP_OP:
|
||||
data->flags |= PMBUS_VOUT_PROTECTED;
|
||||
fallthrough;
|
||||
case PB_WP_VOUT:
|
||||
data->flags |= PMBUS_WRITE_PROTECTED | PMBUS_SKIP_STATUS_CHECK;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data,
|
||||
struct pmbus_driver_info *info)
|
||||
{
|
||||
|
@ -2718,12 +2771,8 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data,
|
|||
* faults, and we should not try it. Also, in that case, writes into
|
||||
* limit registers need to be disabled.
|
||||
*/
|
||||
if (!(data->flags & PMBUS_NO_WRITE_PROTECT)) {
|
||||
ret = _pmbus_read_byte_data(client, -1, PMBUS_WRITE_PROTECT);
|
||||
|
||||
if (ret > 0 && (ret & PB_WP_ANY))
|
||||
data->flags |= PMBUS_WRITE_PROTECTED | PMBUS_SKIP_STATUS_CHECK;
|
||||
}
|
||||
if (!(data->flags & PMBUS_NO_WRITE_PROTECT))
|
||||
pmbus_init_wp(client, data);
|
||||
|
||||
ret = i2c_smbus_read_byte_data(client, PMBUS_REVISION);
|
||||
if (ret >= 0)
|
||||
|
@ -3183,8 +3232,12 @@ static int pmbus_regulator_list_voltage(struct regulator_dev *rdev,
|
|||
{
|
||||
struct device *dev = rdev_get_dev(rdev);
|
||||
struct i2c_client *client = to_i2c_client(dev->parent);
|
||||
struct pmbus_data *data = i2c_get_clientdata(client);
|
||||
int val, low, high;
|
||||
|
||||
if (data->flags & PMBUS_VOUT_PROTECTED)
|
||||
return 0;
|
||||
|
||||
if (selector >= rdev->desc->n_voltages ||
|
||||
selector < rdev->desc->linear_min_sel)
|
||||
return -EINVAL;
|
||||
|
@ -3219,6 +3272,22 @@ const struct regulator_ops pmbus_regulator_ops = {
|
|||
};
|
||||
EXPORT_SYMBOL_NS_GPL(pmbus_regulator_ops, "PMBUS");
|
||||
|
||||
int pmbus_regulator_init_cb(struct regulator_dev *rdev,
|
||||
struct regulator_config *config)
|
||||
{
|
||||
struct pmbus_data *data = config->driver_data;
|
||||
struct regulation_constraints *constraints = rdev->constraints;
|
||||
|
||||
if (data->flags & PMBUS_OP_PROTECTED)
|
||||
constraints->valid_ops_mask &= ~REGULATOR_CHANGE_STATUS;
|
||||
|
||||
if (data->flags & PMBUS_VOUT_PROTECTED)
|
||||
constraints->valid_ops_mask &= ~REGULATOR_CHANGE_VOLTAGE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(pmbus_regulator_init_cb, "PMBUS");
|
||||
|
||||
static int pmbus_regulator_register(struct pmbus_data *data)
|
||||
{
|
||||
struct device *dev = data->dev;
|
||||
|
@ -3465,11 +3534,11 @@ static int pmbus_init_debugfs(struct i2c_client *client,
|
|||
|
||||
/*
|
||||
* Allocate the max possible entries we need.
|
||||
* 6 entries device-specific
|
||||
* 7 entries device-specific
|
||||
* 10 entries page-specific
|
||||
*/
|
||||
entries = devm_kcalloc(data->dev,
|
||||
6 + data->info->pages * 10, sizeof(*entries),
|
||||
7 + data->info->pages * 10, sizeof(*entries),
|
||||
GFP_KERNEL);
|
||||
if (!entries)
|
||||
return -ENOMEM;
|
||||
|
@ -3482,6 +3551,15 @@ static int pmbus_init_debugfs(struct i2c_client *client,
|
|||
* assume that values of the following registers are the same for all
|
||||
* pages and report values only for page 0.
|
||||
*/
|
||||
if (pmbus_check_byte_register(client, 0, PMBUS_REVISION)) {
|
||||
entries[idx].client = client;
|
||||
entries[idx].page = 0;
|
||||
entries[idx].reg = PMBUS_REVISION;
|
||||
debugfs_create_file("revision", 0444, data->debugfs,
|
||||
&entries[idx++],
|
||||
&pmbus_debugfs_ops);
|
||||
}
|
||||
|
||||
if (pmbus_check_block_register(client, 0, PMBUS_MFR_ID)) {
|
||||
entries[idx].client = client;
|
||||
entries[idx].page = 0;
|
||||
|
|
436
drivers/hwmon/pmbus/tps25990.c
Normal file
436
drivers/hwmon/pmbus/tps25990.c
Normal file
|
@ -0,0 +1,436 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// Copyright (c) 2024 BayLibre, SAS.
|
||||
// Author: Jerome Brunet <jbrunet@baylibre.com>
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "pmbus.h"
|
||||
|
||||
#define TPS25990_READ_VAUX 0xd0
|
||||
#define TPS25990_READ_VIN_MIN 0xd1
|
||||
#define TPS25990_READ_VIN_PEAK 0xd2
|
||||
#define TPS25990_READ_IIN_PEAK 0xd4
|
||||
#define TPS25990_READ_PIN_PEAK 0xd5
|
||||
#define TPS25990_READ_TEMP_AVG 0xd6
|
||||
#define TPS25990_READ_TEMP_PEAK 0xd7
|
||||
#define TPS25990_READ_VOUT_MIN 0xda
|
||||
#define TPS25990_READ_VIN_AVG 0xdc
|
||||
#define TPS25990_READ_VOUT_AVG 0xdd
|
||||
#define TPS25990_READ_IIN_AVG 0xde
|
||||
#define TPS25990_READ_PIN_AVG 0xdf
|
||||
#define TPS25990_VIREF 0xe0
|
||||
#define TPS25990_PK_MIN_AVG 0xea
|
||||
#define PK_MIN_AVG_RST_PEAK BIT(7)
|
||||
#define PK_MIN_AVG_RST_AVG BIT(6)
|
||||
#define PK_MIN_AVG_RST_MIN BIT(5)
|
||||
#define PK_MIN_AVG_AVG_CNT GENMASK(2, 0)
|
||||
#define TPS25990_MFR_WRITE_PROTECT 0xf8
|
||||
#define TPS25990_UNLOCKED BIT(7)
|
||||
|
||||
#define TPS25990_8B_SHIFT 2
|
||||
#define TPS25990_VIN_OVF_NUM 525100
|
||||
#define TPS25990_VIN_OVF_DIV 10163
|
||||
#define TPS25990_VIN_OVF_OFF 155
|
||||
#define TPS25990_IIN_OCF_NUM 953800
|
||||
#define TPS25990_IIN_OCF_DIV 129278
|
||||
#define TPS25990_IIN_OCF_OFF 157
|
||||
|
||||
#define PK_MIN_AVG_RST_MASK (PK_MIN_AVG_RST_PEAK | \
|
||||
PK_MIN_AVG_RST_AVG | \
|
||||
PK_MIN_AVG_RST_MIN)
|
||||
|
||||
/*
|
||||
* Arbitrary default Rimon value: 1kOhm
|
||||
* This correspond to an overcurrent limit of 55A, close to the specified limit
|
||||
* of un-stacked TPS25990 and makes further calculation easier to setup in
|
||||
* sensor.conf, if necessary
|
||||
*/
|
||||
#define TPS25990_DEFAULT_RIMON 1000000000
|
||||
|
||||
static void tps25990_set_m(int *m, u32 rimon)
|
||||
{
|
||||
u64 val = ((u64)*m) * rimon;
|
||||
|
||||
/* Make sure m fits the s32 type */
|
||||
*m = DIV_ROUND_CLOSEST_ULL(val, 1000000);
|
||||
}
|
||||
|
||||
static int tps25990_mfr_write_protect_set(struct i2c_client *client,
|
||||
u8 protect)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
switch (protect) {
|
||||
case 0:
|
||||
val = 0xa2;
|
||||
break;
|
||||
case PB_WP_ALL:
|
||||
val = 0x0;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return pmbus_write_byte_data(client, -1, TPS25990_MFR_WRITE_PROTECT,
|
||||
val);
|
||||
}
|
||||
|
||||
static int tps25990_mfr_write_protect_get(struct i2c_client *client)
|
||||
{
|
||||
int ret = pmbus_read_byte_data(client, -1, TPS25990_MFR_WRITE_PROTECT);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return (ret & TPS25990_UNLOCKED) ? 0 : PB_WP_ALL;
|
||||
}
|
||||
|
||||
static int tps25990_read_word_data(struct i2c_client *client,
|
||||
int page, int phase, int reg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (reg) {
|
||||
case PMBUS_VIRT_READ_VIN_MAX:
|
||||
ret = pmbus_read_word_data(client, page, phase,
|
||||
TPS25990_READ_VIN_PEAK);
|
||||
break;
|
||||
|
||||
case PMBUS_VIRT_READ_VIN_MIN:
|
||||
ret = pmbus_read_word_data(client, page, phase,
|
||||
TPS25990_READ_VIN_MIN);
|
||||
break;
|
||||
|
||||
case PMBUS_VIRT_READ_VIN_AVG:
|
||||
ret = pmbus_read_word_data(client, page, phase,
|
||||
TPS25990_READ_VIN_AVG);
|
||||
break;
|
||||
|
||||
case PMBUS_VIRT_READ_VOUT_MIN:
|
||||
ret = pmbus_read_word_data(client, page, phase,
|
||||
TPS25990_READ_VOUT_MIN);
|
||||
break;
|
||||
|
||||
case PMBUS_VIRT_READ_VOUT_AVG:
|
||||
ret = pmbus_read_word_data(client, page, phase,
|
||||
TPS25990_READ_VOUT_AVG);
|
||||
break;
|
||||
|
||||
case PMBUS_VIRT_READ_IIN_AVG:
|
||||
ret = pmbus_read_word_data(client, page, phase,
|
||||
TPS25990_READ_IIN_AVG);
|
||||
break;
|
||||
|
||||
case PMBUS_VIRT_READ_IIN_MAX:
|
||||
ret = pmbus_read_word_data(client, page, phase,
|
||||
TPS25990_READ_IIN_PEAK);
|
||||
break;
|
||||
|
||||
case PMBUS_VIRT_READ_TEMP_AVG:
|
||||
ret = pmbus_read_word_data(client, page, phase,
|
||||
TPS25990_READ_TEMP_AVG);
|
||||
break;
|
||||
|
||||
case PMBUS_VIRT_READ_TEMP_MAX:
|
||||
ret = pmbus_read_word_data(client, page, phase,
|
||||
TPS25990_READ_TEMP_PEAK);
|
||||
break;
|
||||
|
||||
case PMBUS_VIRT_READ_PIN_AVG:
|
||||
ret = pmbus_read_word_data(client, page, phase,
|
||||
TPS25990_READ_PIN_AVG);
|
||||
break;
|
||||
|
||||
case PMBUS_VIRT_READ_PIN_MAX:
|
||||
ret = pmbus_read_word_data(client, page, phase,
|
||||
TPS25990_READ_PIN_PEAK);
|
||||
break;
|
||||
|
||||
case PMBUS_VIRT_READ_VMON:
|
||||
ret = pmbus_read_word_data(client, page, phase,
|
||||
TPS25990_READ_VAUX);
|
||||
break;
|
||||
|
||||
case PMBUS_VIN_UV_WARN_LIMIT:
|
||||
case PMBUS_VIN_UV_FAULT_LIMIT:
|
||||
case PMBUS_VIN_OV_WARN_LIMIT:
|
||||
case PMBUS_VOUT_UV_WARN_LIMIT:
|
||||
case PMBUS_IIN_OC_WARN_LIMIT:
|
||||
case PMBUS_OT_WARN_LIMIT:
|
||||
case PMBUS_OT_FAULT_LIMIT:
|
||||
case PMBUS_PIN_OP_WARN_LIMIT:
|
||||
/*
|
||||
* These registers provide an 8 bits value instead of a
|
||||
* 10bits one. Just shifting twice the register value is
|
||||
* enough to make the sensor type conversion work, even
|
||||
* if the datasheet provides different m, b and R for
|
||||
* those.
|
||||
*/
|
||||
ret = pmbus_read_word_data(client, page, phase, reg);
|
||||
if (ret < 0)
|
||||
break;
|
||||
ret <<= TPS25990_8B_SHIFT;
|
||||
break;
|
||||
|
||||
case PMBUS_VIN_OV_FAULT_LIMIT:
|
||||
ret = pmbus_read_word_data(client, page, phase, reg);
|
||||
if (ret < 0)
|
||||
break;
|
||||
ret = DIV_ROUND_CLOSEST(ret * TPS25990_VIN_OVF_NUM,
|
||||
TPS25990_VIN_OVF_DIV);
|
||||
ret += TPS25990_VIN_OVF_OFF;
|
||||
break;
|
||||
|
||||
case PMBUS_IIN_OC_FAULT_LIMIT:
|
||||
/*
|
||||
* VIREF directly sets the over-current limit at which the eFuse
|
||||
* will turn the FET off and trigger a fault. Expose it through
|
||||
* this generic property instead of a manufacturer specific one.
|
||||
*/
|
||||
ret = pmbus_read_byte_data(client, page, TPS25990_VIREF);
|
||||
if (ret < 0)
|
||||
break;
|
||||
ret = DIV_ROUND_CLOSEST(ret * TPS25990_IIN_OCF_NUM,
|
||||
TPS25990_IIN_OCF_DIV);
|
||||
ret += TPS25990_IIN_OCF_OFF;
|
||||
break;
|
||||
|
||||
case PMBUS_VIRT_SAMPLES:
|
||||
ret = pmbus_read_byte_data(client, page, TPS25990_PK_MIN_AVG);
|
||||
if (ret < 0)
|
||||
break;
|
||||
ret = 1 << FIELD_GET(PK_MIN_AVG_AVG_CNT, ret);
|
||||
break;
|
||||
|
||||
case PMBUS_VIRT_RESET_TEMP_HISTORY:
|
||||
case PMBUS_VIRT_RESET_VIN_HISTORY:
|
||||
case PMBUS_VIRT_RESET_IIN_HISTORY:
|
||||
case PMBUS_VIRT_RESET_PIN_HISTORY:
|
||||
case PMBUS_VIRT_RESET_VOUT_HISTORY:
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -ENODATA;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tps25990_write_word_data(struct i2c_client *client,
|
||||
int page, int reg, u16 value)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (reg) {
|
||||
case PMBUS_VIN_UV_WARN_LIMIT:
|
||||
case PMBUS_VIN_UV_FAULT_LIMIT:
|
||||
case PMBUS_VIN_OV_WARN_LIMIT:
|
||||
case PMBUS_VOUT_UV_WARN_LIMIT:
|
||||
case PMBUS_IIN_OC_WARN_LIMIT:
|
||||
case PMBUS_OT_WARN_LIMIT:
|
||||
case PMBUS_OT_FAULT_LIMIT:
|
||||
case PMBUS_PIN_OP_WARN_LIMIT:
|
||||
value >>= TPS25990_8B_SHIFT;
|
||||
value = clamp_val(value, 0, 0xff);
|
||||
ret = pmbus_write_word_data(client, page, reg, value);
|
||||
break;
|
||||
|
||||
case PMBUS_VIN_OV_FAULT_LIMIT:
|
||||
value -= TPS25990_VIN_OVF_OFF;
|
||||
value = DIV_ROUND_CLOSEST(((unsigned int)value) * TPS25990_VIN_OVF_DIV,
|
||||
TPS25990_VIN_OVF_NUM);
|
||||
value = clamp_val(value, 0, 0xf);
|
||||
ret = pmbus_write_word_data(client, page, reg, value);
|
||||
break;
|
||||
|
||||
case PMBUS_IIN_OC_FAULT_LIMIT:
|
||||
value -= TPS25990_IIN_OCF_OFF;
|
||||
value = DIV_ROUND_CLOSEST(((unsigned int)value) * TPS25990_IIN_OCF_DIV,
|
||||
TPS25990_IIN_OCF_NUM);
|
||||
value = clamp_val(value, 0, 0x3f);
|
||||
ret = pmbus_write_byte_data(client, page, TPS25990_VIREF, value);
|
||||
break;
|
||||
|
||||
case PMBUS_VIRT_SAMPLES:
|
||||
value = clamp_val(value, 1, 1 << PK_MIN_AVG_AVG_CNT);
|
||||
value = ilog2(value);
|
||||
ret = pmbus_update_byte_data(client, page, TPS25990_PK_MIN_AVG,
|
||||
PK_MIN_AVG_AVG_CNT,
|
||||
FIELD_PREP(PK_MIN_AVG_AVG_CNT, value));
|
||||
break;
|
||||
|
||||
case PMBUS_VIRT_RESET_TEMP_HISTORY:
|
||||
case PMBUS_VIRT_RESET_VIN_HISTORY:
|
||||
case PMBUS_VIRT_RESET_IIN_HISTORY:
|
||||
case PMBUS_VIRT_RESET_PIN_HISTORY:
|
||||
case PMBUS_VIRT_RESET_VOUT_HISTORY:
|
||||
/*
|
||||
* TPS25990 has history resets based on MIN/AVG/PEAK instead of per
|
||||
* sensor type. Exposing this quirk in hwmon is not desirable so
|
||||
* reset MIN, AVG and PEAK together. Even is there effectively only
|
||||
* one reset, which resets everything, expose the 5 entries so
|
||||
* userspace is not required map a sensor type to another to trigger
|
||||
* a reset
|
||||
*/
|
||||
ret = pmbus_update_byte_data(client, 0, TPS25990_PK_MIN_AVG,
|
||||
PK_MIN_AVG_RST_MASK,
|
||||
PK_MIN_AVG_RST_MASK);
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -ENODATA;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tps25990_read_byte_data(struct i2c_client *client,
|
||||
int page, int reg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (reg) {
|
||||
case PMBUS_WRITE_PROTECT:
|
||||
ret = tps25990_mfr_write_protect_get(client);
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -ENODATA;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tps25990_write_byte_data(struct i2c_client *client,
|
||||
int page, int reg, u8 byte)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (reg) {
|
||||
case PMBUS_WRITE_PROTECT:
|
||||
ret = tps25990_mfr_write_protect_set(client, byte);
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -ENODATA;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_SENSORS_TPS25990_REGULATOR)
|
||||
static const struct regulator_desc tps25990_reg_desc[] = {
|
||||
PMBUS_REGULATOR_ONE("vout"),
|
||||
};
|
||||
#endif
|
||||
|
||||
static const struct pmbus_driver_info tps25990_base_info = {
|
||||
.pages = 1,
|
||||
.format[PSC_VOLTAGE_IN] = direct,
|
||||
.m[PSC_VOLTAGE_IN] = 5251,
|
||||
.b[PSC_VOLTAGE_IN] = 0,
|
||||
.R[PSC_VOLTAGE_IN] = -2,
|
||||
.format[PSC_VOLTAGE_OUT] = direct,
|
||||
.m[PSC_VOLTAGE_OUT] = 5251,
|
||||
.b[PSC_VOLTAGE_OUT] = 0,
|
||||
.R[PSC_VOLTAGE_OUT] = -2,
|
||||
.format[PSC_TEMPERATURE] = direct,
|
||||
.m[PSC_TEMPERATURE] = 140,
|
||||
.b[PSC_TEMPERATURE] = 32100,
|
||||
.R[PSC_TEMPERATURE] = -2,
|
||||
/*
|
||||
* Current and Power measurement depends on the ohm value
|
||||
* of Rimon. m is multiplied by 1000 below to have an integer
|
||||
* and -3 is added to R to compensate.
|
||||
*/
|
||||
.format[PSC_CURRENT_IN] = direct,
|
||||
.m[PSC_CURRENT_IN] = 9538,
|
||||
.b[PSC_CURRENT_IN] = 0,
|
||||
.R[PSC_CURRENT_IN] = -6,
|
||||
.format[PSC_POWER] = direct,
|
||||
.m[PSC_POWER] = 4901,
|
||||
.b[PSC_POWER] = 0,
|
||||
.R[PSC_POWER] = -7,
|
||||
.func[0] = (PMBUS_HAVE_VIN |
|
||||
PMBUS_HAVE_VOUT |
|
||||
PMBUS_HAVE_VMON |
|
||||
PMBUS_HAVE_IIN |
|
||||
PMBUS_HAVE_PIN |
|
||||
PMBUS_HAVE_TEMP |
|
||||
PMBUS_HAVE_STATUS_VOUT |
|
||||
PMBUS_HAVE_STATUS_IOUT |
|
||||
PMBUS_HAVE_STATUS_INPUT |
|
||||
PMBUS_HAVE_STATUS_TEMP |
|
||||
PMBUS_HAVE_SAMPLES),
|
||||
.read_word_data = tps25990_read_word_data,
|
||||
.write_word_data = tps25990_write_word_data,
|
||||
.read_byte_data = tps25990_read_byte_data,
|
||||
.write_byte_data = tps25990_write_byte_data,
|
||||
|
||||
#if IS_ENABLED(CONFIG_SENSORS_TPS25990_REGULATOR)
|
||||
.reg_desc = tps25990_reg_desc,
|
||||
.num_regulators = ARRAY_SIZE(tps25990_reg_desc),
|
||||
#endif
|
||||
};
|
||||
|
||||
static const struct i2c_device_id tps25990_i2c_id[] = {
|
||||
{ "tps25990" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, tps25990_i2c_id);
|
||||
|
||||
static const struct of_device_id tps25990_of_match[] = {
|
||||
{ .compatible = "ti,tps25990" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tps25990_of_match);
|
||||
|
||||
static int tps25990_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct pmbus_driver_info *info;
|
||||
u32 rimon = TPS25990_DEFAULT_RIMON;
|
||||
int ret;
|
||||
|
||||
ret = device_property_read_u32(dev, "ti,rimon-micro-ohms", &rimon);
|
||||
if (ret < 0 && ret != -EINVAL)
|
||||
return dev_err_probe(dev, ret, "failed to get rimon\n");
|
||||
|
||||
info = devm_kmemdup(dev, &tps25990_base_info, sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Adapt the current and power scale for each instance */
|
||||
tps25990_set_m(&info->m[PSC_CURRENT_IN], rimon);
|
||||
tps25990_set_m(&info->m[PSC_POWER], rimon);
|
||||
|
||||
return pmbus_do_probe(client, info);
|
||||
}
|
||||
|
||||
static struct i2c_driver tps25990_driver = {
|
||||
.driver = {
|
||||
.name = "tps25990",
|
||||
.of_match_table = tps25990_of_match,
|
||||
},
|
||||
.probe = tps25990_probe,
|
||||
.id_table = tps25990_i2c_id,
|
||||
};
|
||||
module_i2c_driver(tps25990_driver);
|
||||
|
||||
MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
|
||||
MODULE_DESCRIPTION("PMBUS driver for TPS25990 eFuse");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_IMPORT_NS("PMBUS");
|
|
@ -497,7 +497,7 @@ static int pwm_fan_probe(struct platform_device *pdev)
|
|||
struct device *hwmon;
|
||||
int ret;
|
||||
const struct hwmon_channel_info **channels;
|
||||
u32 pwm_min_from_stopped = 0;
|
||||
u32 initial_pwm, pwm_min_from_stopped = 0;
|
||||
u32 *fan_channel_config;
|
||||
int channel_count = 1; /* We always have a PWM channel. */
|
||||
int i;
|
||||
|
@ -545,11 +545,21 @@ static int pwm_fan_probe(struct platform_device *pdev)
|
|||
|
||||
ctx->enable_mode = pwm_disable_reg_enable;
|
||||
|
||||
ret = pwm_fan_get_cooling_data(dev, ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* use maximum cooling level if provided */
|
||||
if (ctx->pwm_fan_cooling_levels)
|
||||
initial_pwm = ctx->pwm_fan_cooling_levels[ctx->pwm_fan_max_state];
|
||||
else
|
||||
initial_pwm = MAX_PWM;
|
||||
|
||||
/*
|
||||
* Set duty cycle to maximum allowed and enable PWM output as well as
|
||||
* the regulator. In case of error nothing is changed
|
||||
*/
|
||||
ret = set_pwm(ctx, MAX_PWM);
|
||||
ret = set_pwm(ctx, initial_pwm);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to configure PWM: %d\n", ret);
|
||||
return ret;
|
||||
|
@ -638,16 +648,16 @@ static int pwm_fan_probe(struct platform_device *pdev)
|
|||
channels[1] = &ctx->fan_channel;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(dev->of_node, "fan-stop-to-start-percent",
|
||||
&pwm_min_from_stopped);
|
||||
ret = device_property_read_u32(dev, "fan-stop-to-start-percent",
|
||||
&pwm_min_from_stopped);
|
||||
if (!ret && pwm_min_from_stopped) {
|
||||
ctx->pwm_duty_cycle_from_stopped =
|
||||
DIV_ROUND_UP_ULL(pwm_min_from_stopped *
|
||||
(ctx->pwm_state.period - 1),
|
||||
100);
|
||||
}
|
||||
ret = of_property_read_u32(dev->of_node, "fan-stop-to-start-us",
|
||||
&ctx->pwm_usec_from_stopped);
|
||||
ret = device_property_read_u32(dev, "fan-stop-to-start-us",
|
||||
&ctx->pwm_usec_from_stopped);
|
||||
if (ret)
|
||||
ctx->pwm_usec_from_stopped = 250000;
|
||||
|
||||
|
@ -661,10 +671,6 @@ static int pwm_fan_probe(struct platform_device *pdev)
|
|||
return PTR_ERR(hwmon);
|
||||
}
|
||||
|
||||
ret = pwm_fan_get_cooling_data(dev, ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ctx->pwm_fan_state = ctx->pwm_fan_max_state;
|
||||
if (IS_ENABLED(CONFIG_THERMAL)) {
|
||||
cdev = devm_thermal_of_cooling_device_register(dev,
|
||||
|
|
|
@ -128,10 +128,32 @@ static int rpi_hwmon_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int rpi_hwmon_suspend(struct device *dev)
|
||||
{
|
||||
struct rpi_hwmon_data *data = dev_get_drvdata(dev);
|
||||
|
||||
cancel_delayed_work_sync(&data->get_values_poll_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rpi_hwmon_resume(struct device *dev)
|
||||
{
|
||||
struct rpi_hwmon_data *data = dev_get_drvdata(dev);
|
||||
|
||||
get_values_poll(&data->get_values_poll_work.work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(rpi_hwmon_pm_ops, rpi_hwmon_suspend,
|
||||
rpi_hwmon_resume);
|
||||
|
||||
static struct platform_driver rpi_hwmon_driver = {
|
||||
.probe = rpi_hwmon_probe,
|
||||
.driver = {
|
||||
.name = "raspberrypi-hwmon",
|
||||
.pm = pm_ptr(&rpi_hwmon_pm_ops),
|
||||
},
|
||||
};
|
||||
module_platform_driver(rpi_hwmon_driver);
|
||||
|
|
|
@ -8,15 +8,15 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i3c/device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define DRIVER_NAME "tmp108"
|
||||
|
@ -331,6 +331,10 @@ static int tmp108_common_probe(struct device *dev, struct regmap *regmap, char *
|
|||
u32 config;
|
||||
int err;
|
||||
|
||||
err = devm_regulator_get_enable(dev, "vcc");
|
||||
if (err)
|
||||
return dev_err_probe(dev, err, "Failed to enable regulator\n");
|
||||
|
||||
tmp108 = devm_kzalloc(dev, sizeof(*tmp108), GFP_KERNEL);
|
||||
if (!tmp108)
|
||||
return -ENOMEM;
|
||||
|
@ -417,25 +421,24 @@ static int tmp108_resume(struct device *dev)
|
|||
static DEFINE_SIMPLE_DEV_PM_OPS(tmp108_dev_pm_ops, tmp108_suspend, tmp108_resume);
|
||||
|
||||
static const struct i2c_device_id tmp108_i2c_ids[] = {
|
||||
{ "p3t1085" },
|
||||
{ "tmp108" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, tmp108_i2c_ids);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id tmp108_of_ids[] = {
|
||||
{ .compatible = "nxp,p3t1085", },
|
||||
{ .compatible = "ti,tmp108", },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tmp108_of_ids);
|
||||
#endif
|
||||
|
||||
static struct i2c_driver tmp108_driver = {
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.pm = pm_sleep_ptr(&tmp108_dev_pm_ops),
|
||||
.of_match_table = of_match_ptr(tmp108_of_ids),
|
||||
.of_match_table = tmp108_of_ids,
|
||||
},
|
||||
.probe = tmp108_probe,
|
||||
.id_table = tmp108_i2c_ids,
|
||||
|
|
|
@ -73,6 +73,20 @@
|
|||
*/
|
||||
#define PMBUS_USE_COEFFICIENTS_CMD BIT(5)
|
||||
|
||||
/*
|
||||
* PMBUS_OP_PROTECTED
|
||||
* Set if the chip OPERATION command is protected and protection is not
|
||||
* determined by the standard WRITE_PROTECT command.
|
||||
*/
|
||||
#define PMBUS_OP_PROTECTED BIT(6)
|
||||
|
||||
/*
|
||||
* PMBUS_VOUT_PROTECTED
|
||||
* Set if the chip VOUT_COMMAND command is protected and protection is not
|
||||
* determined by the standard WRITE_PROTECT command.
|
||||
*/
|
||||
#define PMBUS_VOUT_PROTECTED BIT(7)
|
||||
|
||||
struct pmbus_platform_data {
|
||||
u32 flags; /* Device specific flags */
|
||||
|
||||
|
|
|
@ -295,6 +295,10 @@ static inline struct thermal_zone_device *thermal_tripless_zone_device_register(
|
|||
static inline void thermal_zone_device_unregister(struct thermal_zone_device *tz)
|
||||
{ }
|
||||
|
||||
static inline void thermal_zone_device_update(struct thermal_zone_device *tz,
|
||||
enum thermal_notify_event event)
|
||||
{ }
|
||||
|
||||
static inline struct thermal_cooling_device *
|
||||
thermal_cooling_device_register(const char *type, void *devdata,
|
||||
const struct thermal_cooling_device_ops *ops)
|
||||
|
|
Loading…
Add table
Reference in a new issue