Merge tag 'hwmon-for-linus-v4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging
Pull hwmon updates from Guenter Roeck:
"Notable changes:
- added support for LTM4675, LTC3886, LTC2980, LTM2987, LTC2975,
LTC3887, LTC3882, MAX20751, ADM1293, and ADM1294 to PMBus drivers
- added support for IT8732F to it87 driver
- added support for AMD Carrizo to fam15h_power driver
- added support for various new attributes to nct7802 driver
- added support for F81866 and F71868 to f71882fg driver"
* tag 'hwmon-for-linus-v4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (45 commits)
hwmon: (fam15h_power) Add ratio of Tsample to the PTSC period
hwmon: (fam15h_power) Add documentation for new processors support
hwmon: (fam15h_power) Update running_avg_capture bit field to 28
hwmon: (fam15h_power) Rename fam15h_power_is_internal_node0 function
hwmon: (fam15h_power) Add support for AMD Carrizo
hwmon: (ltc2978) Add support for LTM4675
hwmon: (ltc2978) Add polling for chips requiring it
hwmon: (pmbus) Enable PEC if the controller supports it
hwmon: (pmbus) Use BIT macro
hwmon: (ltc2978) Add support for LTC3886
hwmon: (ltc2978) Add support for LTC2980 and LTM2987
hwmon: (ltc2978) Add missing chip IDs for LTC2978 and LTC3882
hwmon: (ltc2978) Use correct ID mask to detect all chips
hwmon: (ltc2978) Introduce helper functions for min and max values
hwmon: (ltc2978) Introduce feature flags
hwmon: (pmbus) Convert command register definitions to enum
hwmon: (ltc2978) Add support for LTC2975
hwmon: (ltc2978) Add support for LTC3887
hwmon: (ltc2978) Add additional chip IDs for LTM4676 and LTM4676A
hwmon: (ltc2978) Add support for LTC3882
...
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
* LM70/TMP121/LM71/LM74 thermometer.
|
||||
|
||||
Required properties:
|
||||
- compatible: one of
|
||||
"ti,lm70"
|
||||
"ti,tmp121"
|
||||
"ti,lm71"
|
||||
"ti,lm74"
|
||||
|
||||
See Documentation/devicetree/bindings/spi/spi-bus.txt for more required and
|
||||
optional properties.
|
||||
|
||||
Example:
|
||||
|
||||
spi_master {
|
||||
temperature-sensor@0 {
|
||||
compatible = "ti,lm70";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <1000000>;
|
||||
};
|
||||
};
|
||||
@@ -3,10 +3,16 @@ ltc2978
|
||||
Required properties:
|
||||
- compatible: should contain one of:
|
||||
* "lltc,ltc2974"
|
||||
* "lltc,ltc2975"
|
||||
* "lltc,ltc2977"
|
||||
* "lltc,ltc2978"
|
||||
* "lltc,ltc2980"
|
||||
* "lltc,ltc3880"
|
||||
* "lltc,ltc3882"
|
||||
* "lltc,ltc3883"
|
||||
* "lltc,ltc3886"
|
||||
* "lltc,ltc3887"
|
||||
* "lltc,ltm2987"
|
||||
* "lltc,ltm4676"
|
||||
- reg: I2C slave address
|
||||
|
||||
@@ -17,10 +23,10 @@ Optional properties:
|
||||
standard binding for regulators; see regulator.txt.
|
||||
|
||||
Valid names of regulators depend on number of supplies supported per device:
|
||||
* ltc2974 : vout0 - vout3
|
||||
* ltc2977 : vout0 - vout7
|
||||
* ltc2974, ltc2975 : vout0 - vout3
|
||||
* ltc2977, ltc2980, ltm2987 : vout0 - vout7
|
||||
* ltc2978 : vout0 - vout7
|
||||
* ltc3880 : vout0 - vout1
|
||||
* ltc3880, ltc3882, ltc3886 : vout0 - vout1
|
||||
* ltc3883 : vout0
|
||||
* ltm4676 : vout0 - vout1
|
||||
|
||||
|
||||
+23
-17
@@ -14,6 +14,10 @@ Supported chips:
|
||||
Prefix: 'adm1276'
|
||||
Addresses scanned: -
|
||||
Datasheet: www.analog.com/static/imported-files/data_sheets/ADM1276.pdf
|
||||
* Analog Devices ADM1293/ADM1294
|
||||
Prefix: 'adm1293', 'adm1294'
|
||||
Addresses scanned: -
|
||||
Datasheet: http://www.analog.com/media/en/technical-documentation/data-sheets/ADM1293_1294.pdf
|
||||
|
||||
Author: Guenter Roeck <linux@roeck-us.net>
|
||||
|
||||
@@ -22,12 +26,12 @@ Description
|
||||
-----------
|
||||
|
||||
This driver supports hardware montoring for Analog Devices ADM1075, ADM1275,
|
||||
and ADM1276 Hot-Swap Controller and Digital Power Monitor.
|
||||
ADM1276, ADM1293, and ADM1294 Hot-Swap Controller and Digital Power Monitors.
|
||||
|
||||
ADM1075, ADM1275, and ADM1276 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, ADM1275, ADM1276, 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 for details on PMBus client drivers.
|
||||
@@ -58,16 +62,16 @@ Sysfs entries
|
||||
The following attributes are supported. Limits are read-write, history reset
|
||||
attributes are write-only, all other attributes are read-only.
|
||||
|
||||
in1_label "vin1" or "vout1" depending on chip variant and
|
||||
configuration. On ADM1075, vout1 reports the voltage on
|
||||
the VAUX pin.
|
||||
in1_input Measured voltage.
|
||||
in1_min Minimum Voltage.
|
||||
in1_max Maximum voltage.
|
||||
in1_min_alarm Voltage low alarm.
|
||||
in1_max_alarm Voltage high alarm.
|
||||
in1_highest Historical maximum voltage.
|
||||
in1_reset_history Write any value to reset history.
|
||||
inX_label "vin1" or "vout1" depending on chip variant and
|
||||
configuration. On ADM1075, ADM1293, and ADM1294,
|
||||
vout1 reports the voltage on the VAUX pin.
|
||||
inX_input Measured voltage.
|
||||
inX_min Minimum Voltage.
|
||||
inX_max Maximum voltage.
|
||||
inX_min_alarm Voltage low alarm.
|
||||
inX_max_alarm Voltage high alarm.
|
||||
inX_highest Historical maximum voltage.
|
||||
inX_reset_history Write any value to reset history.
|
||||
|
||||
curr1_label "iout1"
|
||||
curr1_input Measured current.
|
||||
@@ -86,7 +90,9 @@ curr1_reset_history Write any value to reset history.
|
||||
|
||||
power1_label "pin1"
|
||||
power1_input Input power.
|
||||
power1_input_lowest Lowest observed input power. ADM1293 and ADM1294 only.
|
||||
power1_input_highest Highest observed input power.
|
||||
power1_reset_history Write any value to reset history.
|
||||
|
||||
Power attributes are supported on ADM1075 and ADM1276
|
||||
only.
|
||||
Power attributes are supported on ADM1075, ADM1276,
|
||||
ADM1293, and ADM1294.
|
||||
|
||||
@@ -3,12 +3,13 @@ Kernel driver fam15h_power
|
||||
|
||||
Supported chips:
|
||||
* AMD Family 15h Processors
|
||||
* AMD Family 16h Processors
|
||||
|
||||
Prefix: 'fam15h_power'
|
||||
Addresses scanned: PCI space
|
||||
Datasheets:
|
||||
BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors
|
||||
(not yet published)
|
||||
BIOS and Kernel Developer's Guide (BKDG) For AMD Family 16h Processors
|
||||
|
||||
Author: Andreas Herrmann <herrmann.der.user@googlemail.com>
|
||||
|
||||
@@ -16,10 +17,11 @@ Description
|
||||
-----------
|
||||
|
||||
This driver permits reading of registers providing power information
|
||||
of AMD Family 15h processors.
|
||||
of AMD Family 15h and 16h processors.
|
||||
|
||||
For AMD Family 15h processors the following power values can be
|
||||
calculated using different processor northbridge function registers:
|
||||
For AMD Family 15h and 16h processors the following power values can
|
||||
be calculated using different processor northbridge function
|
||||
registers:
|
||||
|
||||
* BasePwrWatts: Specifies in watts the maximum amount of power
|
||||
consumed by the processor for NB and logic external to the core.
|
||||
|
||||
+21
-12
@@ -38,6 +38,10 @@ Supported chips:
|
||||
Prefix: 'it8728'
|
||||
Addresses scanned: from Super I/O config space (8 I/O ports)
|
||||
Datasheet: Not publicly available
|
||||
* IT8732F
|
||||
Prefix: 'it8732'
|
||||
Addresses scanned: from Super I/O config space (8 I/O ports)
|
||||
Datasheet: Not publicly available
|
||||
* IT8771E
|
||||
Prefix: 'it8771'
|
||||
Addresses scanned: from Super I/O config space (8 I/O ports)
|
||||
@@ -111,9 +115,9 @@ Description
|
||||
-----------
|
||||
|
||||
This driver implements support for the IT8603E, IT8620E, IT8623E, IT8705F,
|
||||
IT8712F, IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8758E,
|
||||
IT8771E, IT8772E, IT8781F, IT8782F, IT8783E/F, IT8786E, IT8790E, and SiS950
|
||||
chips.
|
||||
IT8712F, IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8732F,
|
||||
IT8758E, IT8771E, IT8772E, IT8781F, IT8782F, IT8783E/F, IT8786E, IT8790E, and
|
||||
SiS950 chips.
|
||||
|
||||
These chips are 'Super I/O chips', supporting floppy disks, infrared ports,
|
||||
joysticks and other miscellaneous stuff. For hardware monitoring, they
|
||||
@@ -137,10 +141,10 @@ The IT8716F, IT8718F, IT8720F, IT8721F/IT8758E and later IT8712F revisions
|
||||
have support for 2 additional fans. The additional fans are supported by the
|
||||
driver.
|
||||
|
||||
The IT8716F, IT8718F, IT8720F, IT8721F/IT8758E, IT8781F, IT8782F, IT8783E/F,
|
||||
and late IT8712F and IT8705F also have optional 16-bit tachometer counters
|
||||
for fans 1 to 3. This is better (no more fan clock divider mess) but not
|
||||
compatible with the older chips and revisions. The 16-bit tachometer mode
|
||||
The IT8716F, IT8718F, IT8720F, IT8721F/IT8758E, IT8732F, IT8781F, IT8782F,
|
||||
IT8783E/F, and late IT8712F and IT8705F also have optional 16-bit tachometer
|
||||
counters for fans 1 to 3. This is better (no more fan clock divider mess) but
|
||||
not compatible with the older chips and revisions. The 16-bit tachometer mode
|
||||
is enabled by the driver when one of the above chips is detected.
|
||||
|
||||
The IT8726F is just bit enhanced IT8716F with additional hardware
|
||||
@@ -159,6 +163,9 @@ IT8728F. It only supports 16-bit fan mode.
|
||||
|
||||
The IT8790E supports up to 3 fans. 16-bit fan mode is always enabled.
|
||||
|
||||
The IT8732F supports a closed-loop mode for fan control, but this is not
|
||||
currently implemented by the driver.
|
||||
|
||||
Temperatures are measured in degrees Celsius. An alarm is triggered once
|
||||
when the Overtemperature Shutdown limit is crossed.
|
||||
|
||||
@@ -173,12 +180,14 @@ is done.
|
||||
Voltage sensors (also known as IN sensors) report their values in volts. An
|
||||
alarm is triggered if the voltage has crossed a programmable minimum or
|
||||
maximum limit. Note that minimum in this case always means 'closest to
|
||||
zero'; this is important for negative voltage measurements. All voltage
|
||||
inputs can measure voltages between 0 and 4.08 volts, with a resolution of
|
||||
0.016 volt (except IT8603E, IT8721F/IT8758E and IT8728F: 0.012 volt.) The
|
||||
battery voltage in8 does not have limit registers.
|
||||
zero'; this is important for negative voltage measurements. On most chips, all
|
||||
voltage inputs can measure voltages between 0 and 4.08 volts, with a resolution
|
||||
of 0.016 volt. IT8603E, IT8721F/IT8758E and IT8728F can measure between 0 and
|
||||
3.06 volts, with a resolution of 0.012 volt. IT8732F can measure between 0 and
|
||||
2.8 volts with a resolution of 0.0109 volt. The battery voltage in8 does not
|
||||
have limit registers.
|
||||
|
||||
On the IT8603E, IT8721F/IT8758E, IT8781F, IT8782F, and IT8783E/F, some
|
||||
On the IT8603E, IT8721F/IT8758E, IT8732F, IT8781F, IT8782F, and IT8783E/F, some
|
||||
voltage inputs are internal and scaled inside the chip:
|
||||
* in3 (optional)
|
||||
* in7 (optional for IT8781F, IT8782F, and IT8783E/F)
|
||||
|
||||
+93
-39
@@ -6,6 +6,10 @@ Supported chips:
|
||||
Prefix: 'ltc2974'
|
||||
Addresses scanned: -
|
||||
Datasheet: http://www.linear.com/product/ltc2974
|
||||
* Linear Technology LTC2975
|
||||
Prefix: 'ltc2975'
|
||||
Addresses scanned: -
|
||||
Datasheet: http://www.linear.com/product/ltc2975
|
||||
* Linear Technology LTC2977
|
||||
Prefix: 'ltc2977'
|
||||
Addresses scanned: -
|
||||
@@ -15,14 +19,38 @@ Supported chips:
|
||||
Addresses scanned: -
|
||||
Datasheet: http://www.linear.com/product/ltc2978
|
||||
http://www.linear.com/product/ltc2978a
|
||||
* Linear Technology LTC2980
|
||||
Prefix: 'ltc2980'
|
||||
Addresses scanned: -
|
||||
Datasheet: http://www.linear.com/product/ltc2980
|
||||
* Linear Technology LTC3880
|
||||
Prefix: 'ltc3880'
|
||||
Addresses scanned: -
|
||||
Datasheet: http://www.linear.com/product/ltc3880
|
||||
* Linear Technology LTC3882
|
||||
Prefix: 'ltc3882'
|
||||
Addresses scanned: -
|
||||
Datasheet: http://www.linear.com/product/ltc3882
|
||||
* Linear Technology LTC3883
|
||||
Prefix: 'ltc3883'
|
||||
Addresses scanned: -
|
||||
Datasheet: http://www.linear.com/product/ltc3883
|
||||
* Linear Technology LTC3886
|
||||
Prefix: 'ltc3886'
|
||||
Addresses scanned: -
|
||||
Datasheet: http://www.linear.com/product/ltc3886
|
||||
* Linear Technology LTC3887
|
||||
Prefix: 'ltc3887'
|
||||
Addresses scanned: -
|
||||
Datasheet: http://www.linear.com/product/ltc3887
|
||||
* Linear Technology LTM2987
|
||||
Prefix: 'ltm2987'
|
||||
Addresses scanned: -
|
||||
Datasheet: http://www.linear.com/product/ltm2987
|
||||
* Linear Technology LTM4675
|
||||
Prefix: 'ltm4675'
|
||||
Addresses scanned: -
|
||||
Datasheet: http://www.linear.com/product/ltm4675
|
||||
* Linear Technology LTM4676
|
||||
Prefix: 'ltm4676'
|
||||
Addresses scanned: -
|
||||
@@ -34,11 +62,20 @@ Author: Guenter Roeck <linux@roeck-us.net>
|
||||
Description
|
||||
-----------
|
||||
|
||||
LTC2974 is a quad digital power supply manager. LTC2978 is an octal power supply
|
||||
monitor. LTC2977 is a pin compatible replacement for LTC2978. LTC3880 is a dual
|
||||
output poly-phase step-down DC/DC controller. LTC3883 is a single phase
|
||||
step-down DC/DC controller. LTM4676 is a dual 13A or single 26A uModule
|
||||
regulator.
|
||||
LTC2974 and LTC2975 are quad digital power supply managers.
|
||||
LTC2978 is an octal power supply monitor.
|
||||
LTC2977 is a pin compatible replacement for LTC2978.
|
||||
LTC2980 is a 16-channel Power System Manager, consisting of two LTC2977
|
||||
in a single die. The chip is instantiated and reported as two separate chips
|
||||
on two different I2C bus addresses.
|
||||
LTC3880, LTC3882, LTC3886, and LTC3887 are dual output poly-phase step-down
|
||||
DC/DC controllers.
|
||||
LTC3883 is a single phase step-down DC/DC controller.
|
||||
LTM2987 is a 16-channel Power System Manager with two LTC2977 plus
|
||||
additional components on a single die. The chip is instantiated and reported
|
||||
as two separate chips on two different I2C bus addresses.
|
||||
LTM4675 is a dual 9A or single 18A μModule regulator
|
||||
LTM4676 is a dual 13A or single 26A uModule regulator.
|
||||
|
||||
|
||||
Usage Notes
|
||||
@@ -61,26 +98,32 @@ in1_label "vin"
|
||||
in1_input Measured input voltage.
|
||||
in1_min Minimum input voltage.
|
||||
in1_max Maximum input voltage.
|
||||
LTC2974, LTC2977, and LTC2978 only.
|
||||
LTC2974, LTC2975, LTC2977, LTC2980, LTC2978, and
|
||||
LTM2987 only.
|
||||
in1_lcrit Critical minimum input voltage.
|
||||
LTC2974, LTC2977, and LTC2978 only.
|
||||
LTC2974, LTC2975, LTC2977, LTC2980, LTC2978, and
|
||||
LTM2987 only.
|
||||
in1_crit Critical maximum input voltage.
|
||||
in1_min_alarm Input voltage low alarm.
|
||||
in1_max_alarm Input voltage high alarm.
|
||||
LTC2974, LTC2977, and LTC2978 only.
|
||||
LTC2974, LTC2975, LTC2977, LTC2980, LTC2978, and
|
||||
LTM2987 only.
|
||||
in1_lcrit_alarm Input voltage critical low alarm.
|
||||
LTC2974, LTC2977, and LTC2978 only.
|
||||
LTC2974, LTC2975, LTC2977, LTC2980, LTC2978, and
|
||||
LTM2987 only.
|
||||
in1_crit_alarm Input voltage critical high alarm.
|
||||
in1_lowest Lowest input voltage.
|
||||
LTC2974, LTC2977, and LTC2978 only.
|
||||
LTC2974, LTC2975, LTC2977, LTC2980, LTC2978, and
|
||||
LTM2987 only.
|
||||
in1_highest Highest input voltage.
|
||||
in1_reset_history Reset input voltage history.
|
||||
|
||||
in[N]_label "vout[1-8]".
|
||||
LTC2974: N=2-5
|
||||
LTC2977: N=2-9
|
||||
LTC2974, LTC2975: N=2-5
|
||||
LTC2977, LTC2980, LTM2987: N=2-9
|
||||
LTC2978: N=2-9
|
||||
LTC3880, LTM4676: N=2-3
|
||||
LTC3880, LTC3882, LTC23886 LTC3887, LTM4675, LTM4676:
|
||||
N=2-3
|
||||
LTC3883: N=2
|
||||
in[N]_input Measured output voltage.
|
||||
in[N]_min Minimum output voltage.
|
||||
@@ -91,67 +134,78 @@ in[N]_min_alarm Output voltage low alarm.
|
||||
in[N]_max_alarm Output voltage high alarm.
|
||||
in[N]_lcrit_alarm Output voltage critical low alarm.
|
||||
in[N]_crit_alarm Output voltage critical high alarm.
|
||||
in[N]_lowest Lowest output voltage. LTC2974 and LTC2978 only.
|
||||
in[N]_lowest Lowest output voltage. LTC2974, LTC2975,
|
||||
and LTC2978 only.
|
||||
in[N]_highest Highest output voltage.
|
||||
in[N]_reset_history Reset output voltage history.
|
||||
|
||||
temp[N]_input Measured temperature.
|
||||
On LTC2974, temp[1-4] report external temperatures,
|
||||
and temp5 reports the chip temperature.
|
||||
On LTC2977 and LTC2978, only one temperature measurement
|
||||
is supported and reports the chip temperature.
|
||||
On LTC3880 and LTM4676, temp1 and temp2 report external
|
||||
temperatures, and temp3 reports the chip temperature.
|
||||
On LTC2974 and LTC2975, temp[1-4] report external
|
||||
temperatures, and temp5 reports the chip temperature.
|
||||
On LTC2977, LTC2980, LTC2978, and LTM2987, only one
|
||||
temperature measurement is supported and reports
|
||||
the chip temperature.
|
||||
On LTC3880, LTC3882, LTC3887, LTM4675, and LTM4676,
|
||||
temp1 and temp2 report external temperatures, and temp3
|
||||
reports the chip temperature.
|
||||
On LTC3883, temp1 reports an external temperature,
|
||||
and temp2 reports the chip temperature.
|
||||
temp[N]_min Mimimum temperature. LTC2974, LCT2977, and LTC2978 only.
|
||||
temp[N]_min Mimimum temperature. LTC2974, LCT2977, LTM2980, LTC2978,
|
||||
and LTM2987 only.
|
||||
temp[N]_max Maximum temperature.
|
||||
temp[N]_lcrit Critical low temperature.
|
||||
temp[N]_crit Critical high temperature.
|
||||
temp[N]_min_alarm Temperature low alarm.
|
||||
LTC2974, LTC2977, and LTC2978 only.
|
||||
LTC2974, LTC2975, LTC2977, LTM2980, LTC2978, and
|
||||
LTM2987 only.
|
||||
temp[N]_max_alarm Temperature high alarm.
|
||||
temp[N]_lcrit_alarm Temperature critical low alarm.
|
||||
temp[N]_crit_alarm Temperature critical high alarm.
|
||||
temp[N]_lowest Lowest measured temperature.
|
||||
LTC2974, LTC2977, and LTC2978 only.
|
||||
Not supported for chip temperature sensor on LTC2974.
|
||||
LTC2974, LTC2975, LTC2977, LTM2980, LTC2978, and
|
||||
LTM2987 only.
|
||||
Not supported for chip temperature sensor on LTC2974 and
|
||||
LTC2975.
|
||||
temp[N]_highest Highest measured temperature. Not supported for chip
|
||||
temperature sensor on LTC2974.
|
||||
temperature sensor on LTC2974 and LTC2975.
|
||||
temp[N]_reset_history Reset temperature history. Not supported for chip
|
||||
temperature sensor on LTC2974.
|
||||
temperature sensor on LTC2974 and LTC2975.
|
||||
|
||||
power1_label "pin". LTC3883 only.
|
||||
power1_label "pin". LTC3883 and LTC3886 only.
|
||||
power1_input Measured input power.
|
||||
|
||||
power[N]_label "pout[1-4]".
|
||||
LTC2974: N=1-4
|
||||
LTC2977: Not supported
|
||||
LTC2974, LTC2975: N=1-4
|
||||
LTC2977, LTC2980, LTM2987: Not supported
|
||||
LTC2978: Not supported
|
||||
LTC3880, LTM4676: N=1-2
|
||||
LTC3880, LTC3882, LTC3886, LTC3887, LTM4675, LTM4676:
|
||||
N=1-2
|
||||
LTC3883: N=2
|
||||
power[N]_input Measured output power.
|
||||
|
||||
curr1_label "iin". LTC3880, LTC3883, and LTM4676 only.
|
||||
curr1_label "iin". LTC3880, LTC3883, LTC3886, LTC3887, LTM4675,
|
||||
and LTM4676 only.
|
||||
curr1_input Measured input current.
|
||||
curr1_max Maximum input current.
|
||||
curr1_max_alarm Input current high alarm.
|
||||
curr1_highest Highest input current. LTC3883 only.
|
||||
curr1_reset_history Reset input current history. LTC3883 only.
|
||||
curr1_highest Highest input current. LTC3883 and LTC3886 only.
|
||||
curr1_reset_history Reset input current history. LTC3883 and LTC3886 only.
|
||||
|
||||
curr[N]_label "iout[1-4]".
|
||||
LTC2974: N=1-4
|
||||
LTC2977: not supported
|
||||
LTC2974, LTC2975: N=1-4
|
||||
LTC2977, LTC2980, LTM2987: not supported
|
||||
LTC2978: not supported
|
||||
LTC3880, LTM4676: N=2-3
|
||||
LTC3880, LTC3882, LTC3886, LTC3887, LTM4675, LTM4676:
|
||||
N=2-3
|
||||
LTC3883: N=2
|
||||
curr[N]_input Measured output current.
|
||||
curr[N]_max Maximum output current.
|
||||
curr[N]_crit Critical high output current.
|
||||
curr[N]_lcrit Critical low output current. LTC2974 only.
|
||||
curr[N]_lcrit Critical low output current. LTC2974 and LTC2975 only.
|
||||
curr[N]_max_alarm Output current high alarm.
|
||||
curr[N]_crit_alarm Output current critical high alarm.
|
||||
curr[N]_lcrit_alarm Output current critical low alarm. LTC2974 only.
|
||||
curr[N]_lowest Lowest output current. LTC2974 only.
|
||||
curr[N]_lcrit_alarm Output current critical low alarm.
|
||||
LTC2974 and LTC2975 only.
|
||||
curr[N]_lowest Lowest output current. LTC2974 and LTC2975 only.
|
||||
curr[N]_highest Highest output current.
|
||||
curr[N]_reset_history Reset output current history.
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
Kernel driver max20751
|
||||
======================
|
||||
|
||||
Supported chips:
|
||||
* maxim MAX20751
|
||||
Prefix: 'max20751'
|
||||
Addresses scanned: -
|
||||
Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX20751.pdf
|
||||
Application note: http://pdfserv.maximintegrated.com/en/an/AN5941.pdf
|
||||
|
||||
Author: Guenter Roeck <linux@roeck-us.net>
|
||||
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
This driver supports MAX20751 Multiphase Master with PMBus Interface
|
||||
and Internal Buck Converter.
|
||||
|
||||
The driver is a client driver to the core PMBus driver.
|
||||
Please see Documentation/hwmon/pmbus 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 for
|
||||
details.
|
||||
|
||||
|
||||
Platform data support
|
||||
---------------------
|
||||
|
||||
The driver supports standard PMBus driver platform data.
|
||||
|
||||
|
||||
Sysfs entries
|
||||
-------------
|
||||
|
||||
The following attributes are supported.
|
||||
|
||||
in1_label "vin1"
|
||||
in1_input Measured voltage.
|
||||
in1_min Minimum input voltage.
|
||||
in1_max Maximum input voltage.
|
||||
in1_lcrit Critical minimum input voltage.
|
||||
in1_crit Critical maximum input voltage.
|
||||
in1_min_alarm Input voltage low alarm.
|
||||
in1_lcrit_alarm Input voltage critical low alarm.
|
||||
in1_min_alarm Input voltage low alarm.
|
||||
in1_max_alarm Input voltage high alarm.
|
||||
|
||||
in2_label "vout1"
|
||||
in2_input Measured voltage.
|
||||
in2_min Minimum output voltage.
|
||||
in2_max Maximum output voltage.
|
||||
in2_lcrit Critical minimum output voltage.
|
||||
in2_crit Critical maximum output voltage.
|
||||
in2_min_alarm Output voltage low alarm.
|
||||
in2_lcrit_alarm Output voltage critical low alarm.
|
||||
in2_min_alarm Output voltage low alarm.
|
||||
in2_max_alarm Output voltage high alarm.
|
||||
|
||||
curr1_input Measured output current.
|
||||
curr1_label "iout1"
|
||||
curr1_max Maximum output current.
|
||||
curr1_alarm Current high alarm.
|
||||
|
||||
temp1_input Measured temperature.
|
||||
temp1_max Maximum temperature.
|
||||
temp1_crit Critical high temperature.
|
||||
temp1_max_alarm Chip temperature high alarm.
|
||||
temp1_crit_alarm Chip temperature critical high alarm.
|
||||
|
||||
power1_input Output power.
|
||||
power1_label "pout1"
|
||||
@@ -17,8 +17,7 @@ This driver implements support for the Nuvoton NCT7802Y hardware monitoring
|
||||
chip. NCT7802Y supports 6 temperature sensors, 5 voltage sensors, and 3 fan
|
||||
speed sensors.
|
||||
|
||||
The chip also supports intelligent fan speed control. This functionality is
|
||||
not currently supported by the driver.
|
||||
Smart Fan™ speed control is available via pwmX_auto_point attributes.
|
||||
|
||||
Tested Boards and BIOS Versions
|
||||
-------------------------------
|
||||
|
||||
@@ -23,11 +23,15 @@ Supported chips:
|
||||
http://www.lineagepower.com/oem/pdf/PDT012A0X.pdf
|
||||
http://www.lineagepower.com/oem/pdf/UDT020A0X.pdf
|
||||
http://www.lineagepower.com/oem/pdf/MDT040A0X.pdf
|
||||
* Texas Instruments TPS40400
|
||||
Prefixes: 'tps40400'
|
||||
* Texas Instruments TPS40400, TPS544B20, TPS544B25, TPS544C20, TPS544C25
|
||||
Prefixes: 'tps40400', 'tps544b20', 'tps544b25', 'tps544c20', 'tps544c25'
|
||||
Addresses scanned: -
|
||||
Datasheets:
|
||||
http://www.ti.com/lit/gpn/tps40400
|
||||
http://www.ti.com/lit/gpn/tps544b20
|
||||
http://www.ti.com/lit/gpn/tps544b25
|
||||
http://www.ti.com/lit/gpn/tps544c20
|
||||
http://www.ti.com/lit/gpn/tps544c25
|
||||
* Generic PMBus devices
|
||||
Prefix: 'pmbus'
|
||||
Addresses scanned: -
|
||||
|
||||
@@ -6549,6 +6549,13 @@ S: Maintained
|
||||
F: Documentation/hwmon/max16065
|
||||
F: drivers/hwmon/max16065.c
|
||||
|
||||
MAX20751 HARDWARE MONITOR DRIVER
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/max20751
|
||||
F: drivers/hwmon/max20751.c
|
||||
|
||||
MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER
|
||||
M: "Hans J. Koch" <hjk@hansjkoch.de>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
|
||||
@@ -609,8 +609,8 @@ config SENSORS_IT87
|
||||
depends on !PPC
|
||||
select HWMON_VID
|
||||
help
|
||||
If you say yes here you get support for ITE IT8705F, IT8712F,
|
||||
IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8758E,
|
||||
If you say yes here you get support for ITE IT8705F, IT8712F, IT8716F,
|
||||
IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8732F, IT8758E,
|
||||
IT8771E, IT8772E, IT8781F, IT8782F, IT8783E/F, IT8786E, IT8790E,
|
||||
IT8603E, IT8620E, and IT8623E sensor chips, and the SiS950 clone.
|
||||
|
||||
|
||||
+144
-32
@@ -51,6 +51,7 @@
|
||||
#define SIO_F71808A_ID 0x1001 /* Chipset ID */
|
||||
#define SIO_F71858_ID 0x0507 /* Chipset ID */
|
||||
#define SIO_F71862_ID 0x0601 /* Chipset ID */
|
||||
#define SIO_F71868_ID 0x1106 /* Chipset ID */
|
||||
#define SIO_F71869_ID 0x0814 /* Chipset ID */
|
||||
#define SIO_F71869A_ID 0x1007 /* Chipset ID */
|
||||
#define SIO_F71882_ID 0x0541 /* Chipset ID */
|
||||
@@ -58,7 +59,9 @@
|
||||
#define SIO_F71889E_ID 0x0909 /* Chipset ID */
|
||||
#define SIO_F71889A_ID 0x1005 /* Chipset ID */
|
||||
#define SIO_F8000_ID 0x0581 /* Chipset ID */
|
||||
#define SIO_F81768D_ID 0x1210 /* Chipset ID */
|
||||
#define SIO_F81865_ID 0x0704 /* Chipset ID */
|
||||
#define SIO_F81866_ID 0x1010 /* Chipset ID */
|
||||
|
||||
#define REGION_LENGTH 8
|
||||
#define ADDR_REG_OFFSET 5
|
||||
@@ -69,6 +72,10 @@
|
||||
#define F71882FG_REG_IN(nr) (0x20 + (nr))
|
||||
#define F71882FG_REG_IN1_HIGH 0x32 /* f7188x only */
|
||||
|
||||
#define F81866_REG_IN_STATUS 0x16 /* F81866 only */
|
||||
#define F81866_REG_IN_BEEP 0x17 /* F81866 only */
|
||||
#define F81866_REG_IN1_HIGH 0x3a /* F81866 only */
|
||||
|
||||
#define F71882FG_REG_FAN(nr) (0xA0 + (16 * (nr)))
|
||||
#define F71882FG_REG_FAN_TARGET(nr) (0xA2 + (16 * (nr)))
|
||||
#define F71882FG_REG_FAN_FULL_SPEED(nr) (0xA4 + (16 * (nr)))
|
||||
@@ -101,7 +108,7 @@
|
||||
|
||||
#define F71882FG_REG_START 0x01
|
||||
|
||||
#define F71882FG_MAX_INS 9
|
||||
#define F71882FG_MAX_INS 11
|
||||
|
||||
#define FAN_MIN_DETECT 366 /* Lowest detectable fanspeed */
|
||||
|
||||
@@ -109,14 +116,16 @@ static unsigned short force_id;
|
||||
module_param(force_id, ushort, 0);
|
||||
MODULE_PARM_DESC(force_id, "Override the detected device ID");
|
||||
|
||||
enum chips { f71808e, f71808a, f71858fg, f71862fg, f71869, f71869a, f71882fg,
|
||||
f71889fg, f71889ed, f71889a, f8000, f81865f };
|
||||
enum chips { f71808e, f71808a, f71858fg, f71862fg, f71868a, f71869, f71869a,
|
||||
f71882fg, f71889fg, f71889ed, f71889a, f8000, f81768d, f81865f,
|
||||
f81866a};
|
||||
|
||||
static const char *const f71882fg_names[] = {
|
||||
"f71808e",
|
||||
"f71808a",
|
||||
"f71858fg",
|
||||
"f71862fg",
|
||||
"f71868a",
|
||||
"f71869", /* Both f71869f and f71869e, reg. compatible and same id */
|
||||
"f71869a",
|
||||
"f71882fg",
|
||||
@@ -124,22 +133,27 @@ static const char *const f71882fg_names[] = {
|
||||
"f71889ed",
|
||||
"f71889a",
|
||||
"f8000",
|
||||
"f81768d",
|
||||
"f81865f",
|
||||
"f81866a",
|
||||
};
|
||||
|
||||
static const char f71882fg_has_in[][F71882FG_MAX_INS] = {
|
||||
[f71808e] = { 1, 1, 1, 1, 1, 1, 0, 1, 1 },
|
||||
[f71808a] = { 1, 1, 1, 1, 0, 0, 0, 1, 1 },
|
||||
[f71858fg] = { 1, 1, 1, 0, 0, 0, 0, 0, 0 },
|
||||
[f71862fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
[f71869] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
[f71869a] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
[f71882fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
[f71889fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
[f71889ed] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
[f71889a] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
[f8000] = { 1, 1, 1, 0, 0, 0, 0, 0, 0 },
|
||||
[f81865f] = { 1, 1, 1, 1, 1, 1, 1, 0, 0 },
|
||||
[f71808e] = { 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0 },
|
||||
[f71808a] = { 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0 },
|
||||
[f71858fg] = { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
[f71862fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
|
||||
[f71868a] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
|
||||
[f71869] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
|
||||
[f71869a] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
|
||||
[f71882fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
|
||||
[f71889fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
|
||||
[f71889ed] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
|
||||
[f71889a] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
|
||||
[f8000] = { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
[f81768d] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
[f81865f] = { 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 },
|
||||
[f81866a] = { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
|
||||
};
|
||||
|
||||
static const char f71882fg_has_in1_alarm[] = {
|
||||
@@ -147,6 +161,7 @@ static const char f71882fg_has_in1_alarm[] = {
|
||||
[f71808a] = 0,
|
||||
[f71858fg] = 0,
|
||||
[f71862fg] = 0,
|
||||
[f71868a] = 0,
|
||||
[f71869] = 0,
|
||||
[f71869a] = 0,
|
||||
[f71882fg] = 1,
|
||||
@@ -154,7 +169,9 @@ static const char f71882fg_has_in1_alarm[] = {
|
||||
[f71889ed] = 1,
|
||||
[f71889a] = 1,
|
||||
[f8000] = 0,
|
||||
[f81768d] = 1,
|
||||
[f81865f] = 1,
|
||||
[f81866a] = 1,
|
||||
};
|
||||
|
||||
static const char f71882fg_fan_has_beep[] = {
|
||||
@@ -162,6 +179,7 @@ static const char f71882fg_fan_has_beep[] = {
|
||||
[f71808a] = 0,
|
||||
[f71858fg] = 0,
|
||||
[f71862fg] = 1,
|
||||
[f71868a] = 1,
|
||||
[f71869] = 1,
|
||||
[f71869a] = 1,
|
||||
[f71882fg] = 1,
|
||||
@@ -169,7 +187,9 @@ static const char f71882fg_fan_has_beep[] = {
|
||||
[f71889ed] = 1,
|
||||
[f71889a] = 1,
|
||||
[f8000] = 0,
|
||||
[f81768d] = 1,
|
||||
[f81865f] = 1,
|
||||
[f81866a] = 1,
|
||||
};
|
||||
|
||||
static const char f71882fg_nr_fans[] = {
|
||||
@@ -177,6 +197,7 @@ static const char f71882fg_nr_fans[] = {
|
||||
[f71808a] = 2, /* +1 fan which is monitor + simple pwm only */
|
||||
[f71858fg] = 3,
|
||||
[f71862fg] = 3,
|
||||
[f71868a] = 3,
|
||||
[f71869] = 3,
|
||||
[f71869a] = 3,
|
||||
[f71882fg] = 4,
|
||||
@@ -184,7 +205,9 @@ static const char f71882fg_nr_fans[] = {
|
||||
[f71889ed] = 3,
|
||||
[f71889a] = 3,
|
||||
[f8000] = 3, /* +1 fan which is monitor only */
|
||||
[f81768d] = 3,
|
||||
[f81865f] = 2,
|
||||
[f81866a] = 3,
|
||||
};
|
||||
|
||||
static const char f71882fg_temp_has_beep[] = {
|
||||
@@ -192,6 +215,7 @@ static const char f71882fg_temp_has_beep[] = {
|
||||
[f71808a] = 1,
|
||||
[f71858fg] = 0,
|
||||
[f71862fg] = 1,
|
||||
[f71868a] = 1,
|
||||
[f71869] = 1,
|
||||
[f71869a] = 1,
|
||||
[f71882fg] = 1,
|
||||
@@ -199,7 +223,9 @@ static const char f71882fg_temp_has_beep[] = {
|
||||
[f71889ed] = 1,
|
||||
[f71889a] = 1,
|
||||
[f8000] = 0,
|
||||
[f81768d] = 1,
|
||||
[f81865f] = 1,
|
||||
[f81866a] = 1,
|
||||
};
|
||||
|
||||
static const char f71882fg_nr_temps[] = {
|
||||
@@ -207,6 +233,7 @@ static const char f71882fg_nr_temps[] = {
|
||||
[f71808a] = 2,
|
||||
[f71858fg] = 3,
|
||||
[f71862fg] = 3,
|
||||
[f71868a] = 3,
|
||||
[f71869] = 3,
|
||||
[f71869a] = 3,
|
||||
[f71882fg] = 3,
|
||||
@@ -214,7 +241,9 @@ static const char f71882fg_nr_temps[] = {
|
||||
[f71889ed] = 3,
|
||||
[f71889a] = 3,
|
||||
[f8000] = 3,
|
||||
[f81768d] = 3,
|
||||
[f81865f] = 2,
|
||||
[f81866a] = 3,
|
||||
};
|
||||
|
||||
static struct platform_device *f71882fg_pdev;
|
||||
@@ -490,6 +519,23 @@ static struct sensor_device_attribute_2 fxxxx_temp_beep_attr[3][2] = { {
|
||||
store_temp_beep, 0, 7),
|
||||
} };
|
||||
|
||||
static struct sensor_device_attribute_2 f81866_temp_beep_attr[3][2] = { {
|
||||
SENSOR_ATTR_2(temp1_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
|
||||
store_temp_beep, 0, 0),
|
||||
SENSOR_ATTR_2(temp1_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
|
||||
store_temp_beep, 0, 4),
|
||||
}, {
|
||||
SENSOR_ATTR_2(temp2_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
|
||||
store_temp_beep, 0, 1),
|
||||
SENSOR_ATTR_2(temp2_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
|
||||
store_temp_beep, 0, 5),
|
||||
}, {
|
||||
SENSOR_ATTR_2(temp3_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
|
||||
store_temp_beep, 0, 2),
|
||||
SENSOR_ATTR_2(temp3_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
|
||||
store_temp_beep, 0, 6),
|
||||
} };
|
||||
|
||||
/*
|
||||
* Temp attr for the f8000
|
||||
* Note on the f8000 temp_ovt (crit) is used as max, and temp_high (max)
|
||||
@@ -531,6 +577,8 @@ static struct sensor_device_attribute_2 fxxxx_in_attr[] = {
|
||||
SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6),
|
||||
SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7),
|
||||
SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8),
|
||||
SENSOR_ATTR_2(in9_input, S_IRUGO, show_in, NULL, 0, 9),
|
||||
SENSOR_ATTR_2(in10_input, S_IRUGO, show_in, NULL, 0, 10),
|
||||
};
|
||||
|
||||
/* For models with in1 alarm capability */
|
||||
@@ -1170,10 +1218,21 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
|
||||
if (time_after(jiffies, data->last_limits + 60 * HZ) ||
|
||||
!data->valid) {
|
||||
if (f71882fg_has_in1_alarm[data->type]) {
|
||||
data->in1_max =
|
||||
f71882fg_read8(data, F71882FG_REG_IN1_HIGH);
|
||||
data->in_beep =
|
||||
f71882fg_read8(data, F71882FG_REG_IN_BEEP);
|
||||
if (data->type == f81866a) {
|
||||
data->in1_max =
|
||||
f71882fg_read8(data,
|
||||
F81866_REG_IN1_HIGH);
|
||||
data->in_beep =
|
||||
f71882fg_read8(data,
|
||||
F81866_REG_IN_BEEP);
|
||||
} else {
|
||||
data->in1_max =
|
||||
f71882fg_read8(data,
|
||||
F71882FG_REG_IN1_HIGH);
|
||||
data->in_beep =
|
||||
f71882fg_read8(data,
|
||||
F71882FG_REG_IN_BEEP);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get High & boundary temps*/
|
||||
@@ -1297,9 +1356,16 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
|
||||
data->fan[3] = f71882fg_read16(data,
|
||||
F71882FG_REG_FAN(3));
|
||||
|
||||
if (f71882fg_has_in1_alarm[data->type])
|
||||
data->in_status = f71882fg_read8(data,
|
||||
if (f71882fg_has_in1_alarm[data->type]) {
|
||||
if (data->type == f81866a)
|
||||
data->in_status = f71882fg_read8(data,
|
||||
F81866_REG_IN_STATUS);
|
||||
|
||||
else
|
||||
data->in_status = f71882fg_read8(data,
|
||||
F71882FG_REG_IN_STATUS);
|
||||
}
|
||||
|
||||
for (nr = 0; nr < F71882FG_MAX_INS; nr++)
|
||||
if (f71882fg_has_in[data->type][nr])
|
||||
data->in[nr] = f71882fg_read8(data,
|
||||
@@ -1440,7 +1506,10 @@ static ssize_t store_in_max(struct device *dev, struct device_attribute
|
||||
val = clamp_val(val, 0, 255);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
f71882fg_write8(data, F71882FG_REG_IN1_HIGH, val);
|
||||
if (data->type == f81866a)
|
||||
f71882fg_write8(data, F81866_REG_IN1_HIGH, val);
|
||||
else
|
||||
f71882fg_write8(data, F71882FG_REG_IN1_HIGH, val);
|
||||
data->in1_max = val;
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
@@ -1471,13 +1540,20 @@ static ssize_t store_in_beep(struct device *dev, struct device_attribute
|
||||
return err;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP);
|
||||
if (data->type == f81866a)
|
||||
data->in_beep = f71882fg_read8(data, F81866_REG_IN_BEEP);
|
||||
else
|
||||
data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP);
|
||||
|
||||
if (val)
|
||||
data->in_beep |= 1 << nr;
|
||||
else
|
||||
data->in_beep &= ~(1 << nr);
|
||||
|
||||
f71882fg_write8(data, F71882FG_REG_IN_BEEP, data->in_beep);
|
||||
if (data->type == f81866a)
|
||||
f71882fg_write8(data, F81866_REG_IN_BEEP, data->in_beep);
|
||||
else
|
||||
f71882fg_write8(data, F71882FG_REG_IN_BEEP, data->in_beep);
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
return count;
|
||||
@@ -2270,6 +2346,7 @@ static int f71882fg_probe(struct platform_device *pdev)
|
||||
int nr_fans = f71882fg_nr_fans[sio_data->type];
|
||||
int nr_temps = f71882fg_nr_temps[sio_data->type];
|
||||
int err, i;
|
||||
int size;
|
||||
u8 start_reg, reg;
|
||||
|
||||
data = devm_kzalloc(&pdev->dev, sizeof(struct f71882fg_data),
|
||||
@@ -2280,7 +2357,8 @@ static int f71882fg_probe(struct platform_device *pdev)
|
||||
data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
|
||||
data->type = sio_data->type;
|
||||
data->temp_start =
|
||||
(data->type == f71858fg || data->type == f8000) ? 0 : 1;
|
||||
(data->type == f71858fg || data->type == f8000 ||
|
||||
data->type == f81866a) ? 0 : 1;
|
||||
mutex_init(&data->update_lock);
|
||||
platform_set_drvdata(pdev, data);
|
||||
|
||||
@@ -2322,6 +2400,11 @@ static int f71882fg_probe(struct platform_device *pdev)
|
||||
f8000_temp_attr,
|
||||
ARRAY_SIZE(f8000_temp_attr));
|
||||
break;
|
||||
case f81866a:
|
||||
err = f71882fg_create_sysfs_files(pdev,
|
||||
f71858fg_temp_attr,
|
||||
ARRAY_SIZE(f71858fg_temp_attr));
|
||||
break;
|
||||
default:
|
||||
err = f71882fg_create_sysfs_files(pdev,
|
||||
&fxxxx_temp_attr[0][0],
|
||||
@@ -2331,10 +2414,18 @@ static int f71882fg_probe(struct platform_device *pdev)
|
||||
goto exit_unregister_sysfs;
|
||||
|
||||
if (f71882fg_temp_has_beep[data->type]) {
|
||||
err = f71882fg_create_sysfs_files(pdev,
|
||||
&fxxxx_temp_beep_attr[0][0],
|
||||
ARRAY_SIZE(fxxxx_temp_beep_attr[0])
|
||||
* nr_temps);
|
||||
if (data->type == f81866a) {
|
||||
size = ARRAY_SIZE(f81866_temp_beep_attr[0]);
|
||||
err = f71882fg_create_sysfs_files(pdev,
|
||||
&f81866_temp_beep_attr[0][0],
|
||||
size * nr_temps);
|
||||
|
||||
} else {
|
||||
size = ARRAY_SIZE(fxxxx_temp_beep_attr[0]);
|
||||
err = f71882fg_create_sysfs_files(pdev,
|
||||
&fxxxx_temp_beep_attr[0][0],
|
||||
size * nr_temps);
|
||||
}
|
||||
if (err)
|
||||
goto exit_unregister_sysfs;
|
||||
}
|
||||
@@ -2451,15 +2542,27 @@ static int f71882fg_remove(struct platform_device *pdev)
|
||||
f8000_temp_attr,
|
||||
ARRAY_SIZE(f8000_temp_attr));
|
||||
break;
|
||||
case f81866a:
|
||||
f71882fg_remove_sysfs_files(pdev,
|
||||
f71858fg_temp_attr,
|
||||
ARRAY_SIZE(f71858fg_temp_attr));
|
||||
break;
|
||||
default:
|
||||
f71882fg_remove_sysfs_files(pdev,
|
||||
&fxxxx_temp_attr[0][0],
|
||||
ARRAY_SIZE(fxxxx_temp_attr[0]) * nr_temps);
|
||||
}
|
||||
if (f71882fg_temp_has_beep[data->type]) {
|
||||
f71882fg_remove_sysfs_files(pdev,
|
||||
&fxxxx_temp_beep_attr[0][0],
|
||||
ARRAY_SIZE(fxxxx_temp_beep_attr[0]) * nr_temps);
|
||||
if (data->type == f81866a)
|
||||
f71882fg_remove_sysfs_files(pdev,
|
||||
&f81866_temp_beep_attr[0][0],
|
||||
ARRAY_SIZE(f81866_temp_beep_attr[0])
|
||||
* nr_temps);
|
||||
else
|
||||
f71882fg_remove_sysfs_files(pdev,
|
||||
&fxxxx_temp_beep_attr[0][0],
|
||||
ARRAY_SIZE(fxxxx_temp_beep_attr[0])
|
||||
* nr_temps);
|
||||
}
|
||||
|
||||
for (i = 0; i < F71882FG_MAX_INS; i++) {
|
||||
@@ -2551,6 +2654,9 @@ static int __init f71882fg_find(int sioaddr, struct f71882fg_sio_data *sio_data)
|
||||
case SIO_F71862_ID:
|
||||
sio_data->type = f71862fg;
|
||||
break;
|
||||
case SIO_F71868_ID:
|
||||
sio_data->type = f71868a;
|
||||
break;
|
||||
case SIO_F71869_ID:
|
||||
sio_data->type = f71869;
|
||||
break;
|
||||
@@ -2572,9 +2678,15 @@ static int __init f71882fg_find(int sioaddr, struct f71882fg_sio_data *sio_data)
|
||||
case SIO_F8000_ID:
|
||||
sio_data->type = f8000;
|
||||
break;
|
||||
case SIO_F81768D_ID:
|
||||
sio_data->type = f81768d;
|
||||
break;
|
||||
case SIO_F81865_ID:
|
||||
sio_data->type = f81865f;
|
||||
break;
|
||||
case SIO_F81866_ID:
|
||||
sio_data->type = f81866a;
|
||||
break;
|
||||
default:
|
||||
pr_info("Unsupported Fintek device: %04x\n",
|
||||
(unsigned int)devid);
|
||||
|
||||
@@ -46,6 +46,7 @@ struct fam15h_power_data {
|
||||
unsigned int tdp_to_watts;
|
||||
unsigned int base_tdp;
|
||||
unsigned int processor_pwr_watts;
|
||||
unsigned int cpu_pwr_sample_ratio;
|
||||
};
|
||||
|
||||
static ssize_t show_power(struct device *dev,
|
||||
@@ -59,8 +60,19 @@ static ssize_t show_power(struct device *dev,
|
||||
|
||||
pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5),
|
||||
REG_TDP_RUNNING_AVERAGE, &val);
|
||||
running_avg_capture = (val >> 4) & 0x3fffff;
|
||||
running_avg_capture = sign_extend32(running_avg_capture, 21);
|
||||
|
||||
/*
|
||||
* On Carrizo and later platforms, TdpRunAvgAccCap bit field
|
||||
* is extended to 4:31 from 4:25.
|
||||
*/
|
||||
if (boot_cpu_data.x86 == 0x15 && boot_cpu_data.x86_model >= 0x60) {
|
||||
running_avg_capture = val >> 4;
|
||||
running_avg_capture = sign_extend32(running_avg_capture, 27);
|
||||
} else {
|
||||
running_avg_capture = (val >> 4) & 0x3fffff;
|
||||
running_avg_capture = sign_extend32(running_avg_capture, 21);
|
||||
}
|
||||
|
||||
running_avg_range = (val & 0xf) + 1;
|
||||
|
||||
pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5),
|
||||
@@ -117,7 +129,7 @@ static const struct attribute_group fam15h_power_group = {
|
||||
};
|
||||
__ATTRIBUTE_GROUPS(fam15h_power);
|
||||
|
||||
static bool fam15h_power_is_internal_node0(struct pci_dev *f4)
|
||||
static bool should_load_on_this_node(struct pci_dev *f4)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
@@ -177,7 +189,7 @@ static int fam15h_power_resume(struct pci_dev *pdev)
|
||||
static void fam15h_power_init_data(struct pci_dev *f4,
|
||||
struct fam15h_power_data *data)
|
||||
{
|
||||
u32 val;
|
||||
u32 val, eax, ebx, ecx, edx;
|
||||
u64 tmp;
|
||||
|
||||
pci_read_config_dword(f4, REG_PROCESSOR_TDP, &val);
|
||||
@@ -198,6 +210,19 @@ static void fam15h_power_init_data(struct pci_dev *f4,
|
||||
|
||||
/* convert to microWatt */
|
||||
data->processor_pwr_watts = (tmp * 15625) >> 10;
|
||||
|
||||
cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
/* CPUID Fn8000_0007:EDX[12] indicates to support accumulated power */
|
||||
if (!(edx & BIT(12)))
|
||||
return;
|
||||
|
||||
/*
|
||||
* determine the ratio of the compute unit power accumulator
|
||||
* sample period to the PTSC counter period by executing CPUID
|
||||
* Fn8000_0007:ECX
|
||||
*/
|
||||
data->cpu_pwr_sample_ratio = ecx;
|
||||
}
|
||||
|
||||
static int fam15h_power_probe(struct pci_dev *pdev,
|
||||
@@ -214,7 +239,7 @@ static int fam15h_power_probe(struct pci_dev *pdev,
|
||||
*/
|
||||
tweak_runavg_range(pdev);
|
||||
|
||||
if (!fam15h_power_is_internal_node0(pdev))
|
||||
if (!should_load_on_this_node(pdev))
|
||||
return -ENODEV;
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(struct fam15h_power_data), GFP_KERNEL);
|
||||
@@ -233,6 +258,7 @@ static int fam15h_power_probe(struct pci_dev *pdev,
|
||||
static const struct pci_device_id fam15h_power_id_table[] = {
|
||||
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) },
|
||||
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F4) },
|
||||
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M60H_NB_F4) },
|
||||
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F4) },
|
||||
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F4) },
|
||||
{}
|
||||
|
||||
@@ -1113,7 +1113,6 @@ static int g762_remove(struct i2c_client *client)
|
||||
static struct i2c_driver g762_driver = {
|
||||
.driver = {
|
||||
.name = DRVNAME,
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(g762_dt_match),
|
||||
},
|
||||
.probe = g762_probe,
|
||||
|
||||
+36
-7
@@ -21,6 +21,7 @@
|
||||
* IT8721F Super I/O chip w/LPC interface
|
||||
* IT8726F Super I/O chip w/LPC interface
|
||||
* IT8728F Super I/O chip w/LPC interface
|
||||
* IT8732F Super I/O chip w/LPC interface
|
||||
* IT8758E Super I/O chip w/LPC interface
|
||||
* IT8771E Super I/O chip w/LPC interface
|
||||
* IT8772E Super I/O chip w/LPC interface
|
||||
@@ -69,8 +70,9 @@
|
||||
|
||||
#define DRVNAME "it87"
|
||||
|
||||
enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728, it8771,
|
||||
it8772, it8781, it8782, it8783, it8786, it8790, it8603, it8620 };
|
||||
enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728, it8732,
|
||||
it8771, it8772, it8781, it8782, it8783, it8786, it8790, it8603,
|
||||
it8620 };
|
||||
|
||||
static unsigned short force_id;
|
||||
module_param(force_id, ushort, 0);
|
||||
@@ -148,6 +150,7 @@ static inline void superio_exit(void)
|
||||
#define IT8721F_DEVID 0x8721
|
||||
#define IT8726F_DEVID 0x8726
|
||||
#define IT8728F_DEVID 0x8728
|
||||
#define IT8732F_DEVID 0x8732
|
||||
#define IT8771E_DEVID 0x8771
|
||||
#define IT8772E_DEVID 0x8772
|
||||
#define IT8781F_DEVID 0x8781
|
||||
@@ -265,6 +268,7 @@ struct it87_devices {
|
||||
#define FEAT_VID (1 << 9) /* Set if chip supports VID */
|
||||
#define FEAT_IN7_INTERNAL (1 << 10) /* Set if in7 is internal */
|
||||
#define FEAT_SIX_FANS (1 << 11) /* Supports six fans */
|
||||
#define FEAT_10_9MV_ADC (1 << 12)
|
||||
|
||||
static const struct it87_devices it87_devices[] = {
|
||||
[it87] = {
|
||||
@@ -315,6 +319,15 @@ static const struct it87_devices it87_devices[] = {
|
||||
| FEAT_IN7_INTERNAL,
|
||||
.peci_mask = 0x07,
|
||||
},
|
||||
[it8732] = {
|
||||
.name = "it8732",
|
||||
.suffix = "F",
|
||||
.features = FEAT_NEWER_AUTOPWM | FEAT_16BIT_FANS
|
||||
| FEAT_TEMP_OFFSET | FEAT_TEMP_OLD_PECI | FEAT_TEMP_PECI
|
||||
| FEAT_10_9MV_ADC | FEAT_IN7_INTERNAL,
|
||||
.peci_mask = 0x07,
|
||||
.old_peci_mask = 0x02, /* Actually reports PCH */
|
||||
},
|
||||
[it8771] = {
|
||||
.name = "it8771",
|
||||
.suffix = "E",
|
||||
@@ -391,6 +404,7 @@ static const struct it87_devices it87_devices[] = {
|
||||
|
||||
#define has_16bit_fans(data) ((data)->features & FEAT_16BIT_FANS)
|
||||
#define has_12mv_adc(data) ((data)->features & FEAT_12MV_ADC)
|
||||
#define has_10_9mv_adc(data) ((data)->features & FEAT_10_9MV_ADC)
|
||||
#define has_newer_autopwm(data) ((data)->features & FEAT_NEWER_AUTOPWM)
|
||||
#define has_old_autopwm(data) ((data)->features & FEAT_OLD_AUTOPWM)
|
||||
#define has_temp_offset(data) ((data)->features & FEAT_TEMP_OFFSET)
|
||||
@@ -475,7 +489,14 @@ struct it87_data {
|
||||
|
||||
static int adc_lsb(const struct it87_data *data, int nr)
|
||||
{
|
||||
int lsb = has_12mv_adc(data) ? 12 : 16;
|
||||
int lsb;
|
||||
|
||||
if (has_12mv_adc(data))
|
||||
lsb = 120;
|
||||
else if (has_10_9mv_adc(data))
|
||||
lsb = 109;
|
||||
else
|
||||
lsb = 160;
|
||||
if (data->in_scaled & (1 << nr))
|
||||
lsb <<= 1;
|
||||
return lsb;
|
||||
@@ -483,13 +504,13 @@ static int adc_lsb(const struct it87_data *data, int nr)
|
||||
|
||||
static u8 in_to_reg(const struct it87_data *data, int nr, long val)
|
||||
{
|
||||
val = DIV_ROUND_CLOSEST(val, adc_lsb(data, nr));
|
||||
val = DIV_ROUND_CLOSEST(val * 10, adc_lsb(data, nr));
|
||||
return clamp_val(val, 0, 255);
|
||||
}
|
||||
|
||||
static int in_from_reg(const struct it87_data *data, int nr, int val)
|
||||
{
|
||||
return val * adc_lsb(data, nr);
|
||||
return DIV_ROUND_CLOSEST(val * adc_lsb(data, nr), 10);
|
||||
}
|
||||
|
||||
static inline u8 FAN_TO_REG(long rpm, int div)
|
||||
@@ -1515,9 +1536,14 @@ static ssize_t show_label(struct device *dev, struct device_attribute *attr,
|
||||
};
|
||||
struct it87_data *data = dev_get_drvdata(dev);
|
||||
int nr = to_sensor_dev_attr(attr)->index;
|
||||
const char *label;
|
||||
|
||||
return sprintf(buf, "%s\n", has_12mv_adc(data) ? labels_it8721[nr]
|
||||
: labels[nr]);
|
||||
if (has_12mv_adc(data) || has_10_9mv_adc(data))
|
||||
label = labels_it8721[nr];
|
||||
else
|
||||
label = labels[nr];
|
||||
|
||||
return sprintf(buf, "%s\n", label);
|
||||
}
|
||||
static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL, 0);
|
||||
static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 1);
|
||||
@@ -1853,6 +1879,9 @@ static int __init it87_find(unsigned short *address,
|
||||
case IT8728F_DEVID:
|
||||
sio_data->type = it8728;
|
||||
break;
|
||||
case IT8732F_DEVID:
|
||||
sio_data->type = it8732;
|
||||
break;
|
||||
case IT8771E_DEVID:
|
||||
sio_data->type = it8771;
|
||||
break;
|
||||
|
||||
+33
-1
@@ -37,6 +37,7 @@
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
|
||||
#define DRVNAME "lm70"
|
||||
@@ -130,11 +131,41 @@ ATTRIBUTE_GROUPS(lm70);
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id lm70_of_ids[] = {
|
||||
{
|
||||
.compatible = "ti,lm70",
|
||||
.data = (void *) LM70_CHIP_LM70,
|
||||
},
|
||||
{
|
||||
.compatible = "ti,tmp121",
|
||||
.data = (void *) LM70_CHIP_TMP121,
|
||||
},
|
||||
{
|
||||
.compatible = "ti,lm71",
|
||||
.data = (void *) LM70_CHIP_LM71,
|
||||
},
|
||||
{
|
||||
.compatible = "ti,lm74",
|
||||
.data = (void *) LM70_CHIP_LM74,
|
||||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lm70_of_ids);
|
||||
#endif
|
||||
|
||||
static int lm70_probe(struct spi_device *spi)
|
||||
{
|
||||
int chip = spi_get_device_id(spi)->driver_data;
|
||||
const struct of_device_id *match;
|
||||
struct device *hwmon_dev;
|
||||
struct lm70 *p_lm70;
|
||||
int chip;
|
||||
|
||||
match = of_match_device(lm70_of_ids, &spi->dev);
|
||||
if (match)
|
||||
chip = (int)(uintptr_t)match->data;
|
||||
else
|
||||
chip = spi_get_device_id(spi)->driver_data;
|
||||
|
||||
/* signaling is SPI_MODE_0 */
|
||||
if (spi->mode & (SPI_CPOL | SPI_CPHA))
|
||||
@@ -169,6 +200,7 @@ static struct spi_driver lm70_driver = {
|
||||
.driver = {
|
||||
.name = "lm70",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(lm70_of_ids),
|
||||
},
|
||||
.id_table = lm70_ids,
|
||||
.probe = lm70_probe,
|
||||
|
||||
+304
-13
@@ -49,10 +49,13 @@ static const u8 REG_VOLTAGE_LIMIT_MSB_SHIFT[2][5] = {
|
||||
#define REG_VOLTAGE_LOW 0x0f
|
||||
#define REG_FANCOUNT_LOW 0x13
|
||||
#define REG_START 0x21
|
||||
#define REG_MODE 0x22
|
||||
#define REG_MODE 0x22 /* 7.2.32 Mode Selection Register */
|
||||
#define REG_PECI_ENABLE 0x23
|
||||
#define REG_FAN_ENABLE 0x24
|
||||
#define REG_VMON_ENABLE 0x25
|
||||
#define REG_PWM(x) (0x60 + (x))
|
||||
#define REG_SMARTFAN_EN(x) (0x64 + (x) / 2)
|
||||
#define SMARTFAN_EN_SHIFT(x) ((x) % 2 * 4)
|
||||
#define REG_VENDOR_ID 0xfd
|
||||
#define REG_CHIP_ID 0xfe
|
||||
#define REG_VERSION_ID 0xff
|
||||
@@ -66,6 +69,129 @@ struct nct7802_data {
|
||||
struct mutex access_lock; /* for multi-byte read and write operations */
|
||||
};
|
||||
|
||||
static ssize_t show_temp_type(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct nct7802_data *data = dev_get_drvdata(dev);
|
||||
struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
|
||||
unsigned int mode;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(data->regmap, REG_MODE, &mode);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return sprintf(buf, "%u\n", (mode >> (2 * sattr->index) & 3) + 2);
|
||||
}
|
||||
|
||||
static ssize_t store_temp_type(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct nct7802_data *data = dev_get_drvdata(dev);
|
||||
struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
|
||||
unsigned int type;
|
||||
int err;
|
||||
|
||||
err = kstrtouint(buf, 0, &type);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (sattr->index == 2 && type != 4) /* RD3 */
|
||||
return -EINVAL;
|
||||
if (type < 3 || type > 4)
|
||||
return -EINVAL;
|
||||
err = regmap_update_bits(data->regmap, REG_MODE,
|
||||
3 << 2 * sattr->index, (type - 2) << 2 * sattr->index);
|
||||
return err ? : count;
|
||||
}
|
||||
|
||||
static ssize_t show_pwm_mode(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
|
||||
struct nct7802_data *data = dev_get_drvdata(dev);
|
||||
unsigned int regval;
|
||||
int ret;
|
||||
|
||||
if (sattr->index > 1)
|
||||
return sprintf(buf, "1\n");
|
||||
|
||||
ret = regmap_read(data->regmap, 0x5E, ®val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return sprintf(buf, "%u\n", !(regval & (1 << sattr->index)));
|
||||
}
|
||||
|
||||
static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
|
||||
char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct nct7802_data *data = dev_get_drvdata(dev);
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
if (!attr->index)
|
||||
return sprintf(buf, "255\n");
|
||||
|
||||
ret = regmap_read(data->regmap, attr->index, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return sprintf(buf, "%d\n", val);
|
||||
}
|
||||
|
||||
static ssize_t store_pwm(struct device *dev, struct device_attribute *devattr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct nct7802_data *data = dev_get_drvdata(dev);
|
||||
int err;
|
||||
u8 val;
|
||||
|
||||
err = kstrtou8(buf, 0, &val);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = regmap_write(data->regmap, attr->index, val);
|
||||
return err ? : count;
|
||||
}
|
||||
|
||||
static ssize_t show_pwm_enable(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct nct7802_data *data = dev_get_drvdata(dev);
|
||||
struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
|
||||
unsigned int reg, enabled;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(data->regmap, REG_SMARTFAN_EN(sattr->index), ®);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
enabled = reg >> SMARTFAN_EN_SHIFT(sattr->index) & 1;
|
||||
return sprintf(buf, "%u\n", enabled + 1);
|
||||
}
|
||||
|
||||
static ssize_t store_pwm_enable(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct nct7802_data *data = dev_get_drvdata(dev);
|
||||
struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
|
||||
u8 val;
|
||||
int ret;
|
||||
|
||||
ret = kstrtou8(buf, 0, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (val < 1 || val > 2)
|
||||
return -EINVAL;
|
||||
ret = regmap_update_bits(data->regmap, REG_SMARTFAN_EN(sattr->index),
|
||||
1 << SMARTFAN_EN_SHIFT(sattr->index),
|
||||
(val - 1) << SMARTFAN_EN_SHIFT(sattr->index));
|
||||
return ret ? : count;
|
||||
}
|
||||
|
||||
static int nct7802_read_temp(struct nct7802_data *data,
|
||||
u8 reg_temp, u8 reg_temp_low, int *temp)
|
||||
{
|
||||
@@ -377,6 +503,8 @@ store_beep(struct device *dev, struct device_attribute *attr, const char *buf,
|
||||
return err ? : count;
|
||||
}
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO | S_IWUSR,
|
||||
show_temp_type, store_temp_type, 0);
|
||||
static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0x01,
|
||||
REG_TEMP_LSB);
|
||||
static SENSOR_DEVICE_ATTR_2(temp1_min, S_IRUGO | S_IWUSR, show_temp,
|
||||
@@ -386,6 +514,8 @@ static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp,
|
||||
static SENSOR_DEVICE_ATTR_2(temp1_crit, S_IRUGO | S_IWUSR, show_temp,
|
||||
store_temp, 0x3a, 0);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO | S_IWUSR,
|
||||
show_temp_type, store_temp_type, 1);
|
||||
static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0x02,
|
||||
REG_TEMP_LSB);
|
||||
static SENSOR_DEVICE_ATTR_2(temp2_min, S_IRUGO | S_IWUSR, show_temp,
|
||||
@@ -395,6 +525,8 @@ static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp,
|
||||
static SENSOR_DEVICE_ATTR_2(temp2_crit, S_IRUGO | S_IWUSR, show_temp,
|
||||
store_temp, 0x3b, 0);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO | S_IWUSR,
|
||||
show_temp_type, store_temp_type, 2);
|
||||
static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0x03,
|
||||
REG_TEMP_LSB);
|
||||
static SENSOR_DEVICE_ATTR_2(temp3_min, S_IRUGO | S_IWUSR, show_temp,
|
||||
@@ -475,6 +607,7 @@ static SENSOR_DEVICE_ATTR_2(temp6_beep, S_IRUGO | S_IWUSR, show_beep,
|
||||
store_beep, 0x5c, 5);
|
||||
|
||||
static struct attribute *nct7802_temp_attrs[] = {
|
||||
&sensor_dev_attr_temp1_type.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_min.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_max.dev_attr.attr,
|
||||
@@ -485,7 +618,8 @@ static struct attribute *nct7802_temp_attrs[] = {
|
||||
&sensor_dev_attr_temp1_fault.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_beep.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_temp2_input.dev_attr.attr, /* 9 */
|
||||
&sensor_dev_attr_temp2_type.dev_attr.attr, /* 10 */
|
||||
&sensor_dev_attr_temp2_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp2_min.dev_attr.attr,
|
||||
&sensor_dev_attr_temp2_max.dev_attr.attr,
|
||||
&sensor_dev_attr_temp2_crit.dev_attr.attr,
|
||||
@@ -495,7 +629,8 @@ static struct attribute *nct7802_temp_attrs[] = {
|
||||
&sensor_dev_attr_temp2_fault.dev_attr.attr,
|
||||
&sensor_dev_attr_temp2_beep.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_temp3_input.dev_attr.attr, /* 18 */
|
||||
&sensor_dev_attr_temp3_type.dev_attr.attr, /* 20 */
|
||||
&sensor_dev_attr_temp3_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp3_min.dev_attr.attr,
|
||||
&sensor_dev_attr_temp3_max.dev_attr.attr,
|
||||
&sensor_dev_attr_temp3_crit.dev_attr.attr,
|
||||
@@ -505,7 +640,7 @@ static struct attribute *nct7802_temp_attrs[] = {
|
||||
&sensor_dev_attr_temp3_fault.dev_attr.attr,
|
||||
&sensor_dev_attr_temp3_beep.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_temp4_input.dev_attr.attr, /* 27 */
|
||||
&sensor_dev_attr_temp4_input.dev_attr.attr, /* 30 */
|
||||
&sensor_dev_attr_temp4_min.dev_attr.attr,
|
||||
&sensor_dev_attr_temp4_max.dev_attr.attr,
|
||||
&sensor_dev_attr_temp4_crit.dev_attr.attr,
|
||||
@@ -514,7 +649,7 @@ static struct attribute *nct7802_temp_attrs[] = {
|
||||
&sensor_dev_attr_temp4_crit_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_temp4_beep.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_temp5_input.dev_attr.attr, /* 35 */
|
||||
&sensor_dev_attr_temp5_input.dev_attr.attr, /* 38 */
|
||||
&sensor_dev_attr_temp5_min.dev_attr.attr,
|
||||
&sensor_dev_attr_temp5_max.dev_attr.attr,
|
||||
&sensor_dev_attr_temp5_crit.dev_attr.attr,
|
||||
@@ -523,7 +658,7 @@ static struct attribute *nct7802_temp_attrs[] = {
|
||||
&sensor_dev_attr_temp5_crit_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_temp5_beep.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_temp6_input.dev_attr.attr, /* 43 */
|
||||
&sensor_dev_attr_temp6_input.dev_attr.attr, /* 46 */
|
||||
&sensor_dev_attr_temp6_beep.dev_attr.attr,
|
||||
|
||||
NULL
|
||||
@@ -541,25 +676,27 @@ static umode_t nct7802_temp_is_visible(struct kobject *kobj,
|
||||
if (err < 0)
|
||||
return 0;
|
||||
|
||||
if (index < 9 &&
|
||||
if (index < 10 &&
|
||||
(reg & 03) != 0x01 && (reg & 0x03) != 0x02) /* RD1 */
|
||||
return 0;
|
||||
if (index >= 9 && index < 18 &&
|
||||
|
||||
if (index >= 10 && index < 20 &&
|
||||
(reg & 0x0c) != 0x04 && (reg & 0x0c) != 0x08) /* RD2 */
|
||||
return 0;
|
||||
if (index >= 18 && index < 27 && (reg & 0x30) != 0x20) /* RD3 */
|
||||
if (index >= 20 && index < 30 && (reg & 0x30) != 0x20) /* RD3 */
|
||||
return 0;
|
||||
if (index >= 27 && index < 35) /* local */
|
||||
|
||||
if (index >= 30 && index < 38) /* local */
|
||||
return attr->mode;
|
||||
|
||||
err = regmap_read(data->regmap, REG_PECI_ENABLE, ®);
|
||||
if (err < 0)
|
||||
return 0;
|
||||
|
||||
if (index >= 35 && index < 43 && !(reg & 0x01)) /* PECI 0 */
|
||||
if (index >= 38 && index < 46 && !(reg & 0x01)) /* PECI 0 */
|
||||
return 0;
|
||||
|
||||
if (index >= 0x43 && (!(reg & 0x02))) /* PECI 1 */
|
||||
if (index >= 0x46 && (!(reg & 0x02))) /* PECI 1 */
|
||||
return 0;
|
||||
|
||||
return attr->mode;
|
||||
@@ -687,6 +824,27 @@ static SENSOR_DEVICE_ATTR_2(fan3_alarm, S_IRUGO, show_alarm, NULL, 0x1a, 2);
|
||||
static SENSOR_DEVICE_ATTR_2(fan3_beep, S_IRUGO | S_IWUSR, show_beep, store_beep,
|
||||
0x5b, 2);
|
||||
|
||||
/* 7.2.89 Fan Control Output Type */
|
||||
static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO, show_pwm_mode, NULL, 0);
|
||||
static SENSOR_DEVICE_ATTR(pwm2_mode, S_IRUGO, show_pwm_mode, NULL, 1);
|
||||
static SENSOR_DEVICE_ATTR(pwm3_mode, S_IRUGO, show_pwm_mode, NULL, 2);
|
||||
|
||||
/* 7.2.91... Fan Control Output Value */
|
||||
static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, store_pwm,
|
||||
REG_PWM(0));
|
||||
static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, store_pwm,
|
||||
REG_PWM(1));
|
||||
static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm, store_pwm,
|
||||
REG_PWM(2));
|
||||
|
||||
/* 7.2.95... Temperature to Fan mapping Relationships Register */
|
||||
static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, show_pwm_enable,
|
||||
store_pwm_enable, 0);
|
||||
static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR, show_pwm_enable,
|
||||
store_pwm_enable, 1);
|
||||
static SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR, show_pwm_enable,
|
||||
store_pwm_enable, 2);
|
||||
|
||||
static struct attribute *nct7802_fan_attrs[] = {
|
||||
&sensor_dev_attr_fan1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan1_min.dev_attr.attr,
|
||||
@@ -725,10 +883,142 @@ static struct attribute_group nct7802_fan_group = {
|
||||
.is_visible = nct7802_fan_is_visible,
|
||||
};
|
||||
|
||||
static struct attribute *nct7802_pwm_attrs[] = {
|
||||
&sensor_dev_attr_pwm1_enable.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm1_mode.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm1.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm2_enable.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm2_mode.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm2.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm3_enable.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm3_mode.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm3.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group nct7802_pwm_group = {
|
||||
.attrs = nct7802_pwm_attrs,
|
||||
};
|
||||
|
||||
/* 7.2.115... 0x80-0x83, 0x84 Temperature (X-axis) transition */
|
||||
static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_temp, S_IRUGO | S_IWUSR,
|
||||
show_temp, store_temp, 0x80, 0);
|
||||
static SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_temp, S_IRUGO | S_IWUSR,
|
||||
show_temp, store_temp, 0x81, 0);
|
||||
static SENSOR_DEVICE_ATTR_2(pwm1_auto_point3_temp, S_IRUGO | S_IWUSR,
|
||||
show_temp, store_temp, 0x82, 0);
|
||||
static SENSOR_DEVICE_ATTR_2(pwm1_auto_point4_temp, S_IRUGO | S_IWUSR,
|
||||
show_temp, store_temp, 0x83, 0);
|
||||
static SENSOR_DEVICE_ATTR_2(pwm1_auto_point5_temp, S_IRUGO | S_IWUSR,
|
||||
show_temp, store_temp, 0x84, 0);
|
||||
|
||||
/* 7.2.120... 0x85-0x88 PWM (Y-axis) transition */
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IRUGO | S_IWUSR,
|
||||
show_pwm, store_pwm, 0x85);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IRUGO | S_IWUSR,
|
||||
show_pwm, store_pwm, 0x86);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point3_pwm, S_IRUGO | S_IWUSR,
|
||||
show_pwm, store_pwm, 0x87);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point4_pwm, S_IRUGO | S_IWUSR,
|
||||
show_pwm, store_pwm, 0x88);
|
||||
static SENSOR_DEVICE_ATTR(pwm1_auto_point5_pwm, S_IRUGO, show_pwm, NULL, 0);
|
||||
|
||||
/* 7.2.124 Table 2 X-axis Transition Point 1 Register */
|
||||
static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_temp, S_IRUGO | S_IWUSR,
|
||||
show_temp, store_temp, 0x90, 0);
|
||||
static SENSOR_DEVICE_ATTR_2(pwm2_auto_point2_temp, S_IRUGO | S_IWUSR,
|
||||
show_temp, store_temp, 0x91, 0);
|
||||
static SENSOR_DEVICE_ATTR_2(pwm2_auto_point3_temp, S_IRUGO | S_IWUSR,
|
||||
show_temp, store_temp, 0x92, 0);
|
||||
static SENSOR_DEVICE_ATTR_2(pwm2_auto_point4_temp, S_IRUGO | S_IWUSR,
|
||||
show_temp, store_temp, 0x93, 0);
|
||||
static SENSOR_DEVICE_ATTR_2(pwm2_auto_point5_temp, S_IRUGO | S_IWUSR,
|
||||
show_temp, store_temp, 0x94, 0);
|
||||
|
||||
/* 7.2.129 Table 2 Y-axis Transition Point 1 Register */
|
||||
static SENSOR_DEVICE_ATTR(pwm2_auto_point1_pwm, S_IRUGO | S_IWUSR,
|
||||
show_pwm, store_pwm, 0x95);
|
||||
static SENSOR_DEVICE_ATTR(pwm2_auto_point2_pwm, S_IRUGO | S_IWUSR,
|
||||
show_pwm, store_pwm, 0x96);
|
||||
static SENSOR_DEVICE_ATTR(pwm2_auto_point3_pwm, S_IRUGO | S_IWUSR,
|
||||
show_pwm, store_pwm, 0x97);
|
||||
static SENSOR_DEVICE_ATTR(pwm2_auto_point4_pwm, S_IRUGO | S_IWUSR,
|
||||
show_pwm, store_pwm, 0x98);
|
||||
static SENSOR_DEVICE_ATTR(pwm2_auto_point5_pwm, S_IRUGO, show_pwm, NULL, 0);
|
||||
|
||||
/* 7.2.133 Table 3 X-axis Transition Point 1 Register */
|
||||
static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_temp, S_IRUGO | S_IWUSR,
|
||||
show_temp, store_temp, 0xA0, 0);
|
||||
static SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_temp, S_IRUGO | S_IWUSR,
|
||||
show_temp, store_temp, 0xA1, 0);
|
||||
static SENSOR_DEVICE_ATTR_2(pwm3_auto_point3_temp, S_IRUGO | S_IWUSR,
|
||||
show_temp, store_temp, 0xA2, 0);
|
||||
static SENSOR_DEVICE_ATTR_2(pwm3_auto_point4_temp, S_IRUGO | S_IWUSR,
|
||||
show_temp, store_temp, 0xA3, 0);
|
||||
static SENSOR_DEVICE_ATTR_2(pwm3_auto_point5_temp, S_IRUGO | S_IWUSR,
|
||||
show_temp, store_temp, 0xA4, 0);
|
||||
|
||||
/* 7.2.138 Table 3 Y-axis Transition Point 1 Register */
|
||||
static SENSOR_DEVICE_ATTR(pwm3_auto_point1_pwm, S_IRUGO | S_IWUSR,
|
||||
show_pwm, store_pwm, 0xA5);
|
||||
static SENSOR_DEVICE_ATTR(pwm3_auto_point2_pwm, S_IRUGO | S_IWUSR,
|
||||
show_pwm, store_pwm, 0xA6);
|
||||
static SENSOR_DEVICE_ATTR(pwm3_auto_point3_pwm, S_IRUGO | S_IWUSR,
|
||||
show_pwm, store_pwm, 0xA7);
|
||||
static SENSOR_DEVICE_ATTR(pwm3_auto_point4_pwm, S_IRUGO | S_IWUSR,
|
||||
show_pwm, store_pwm, 0xA8);
|
||||
static SENSOR_DEVICE_ATTR(pwm3_auto_point5_pwm, S_IRUGO, show_pwm, NULL, 0);
|
||||
|
||||
static struct attribute *nct7802_auto_point_attrs[] = {
|
||||
&sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm1_auto_point5_temp.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm1_auto_point4_pwm.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm1_auto_point5_pwm.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_pwm2_auto_point1_temp.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm2_auto_point2_temp.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm2_auto_point3_temp.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm2_auto_point4_temp.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm2_auto_point5_temp.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm2_auto_point3_pwm.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm2_auto_point4_pwm.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm2_auto_point5_pwm.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_pwm3_auto_point1_temp.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm3_auto_point2_temp.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm3_auto_point3_temp.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm3_auto_point4_temp.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm3_auto_point5_temp.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm3_auto_point3_pwm.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm3_auto_point4_pwm.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm3_auto_point5_pwm.dev_attr.attr,
|
||||
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group nct7802_auto_point_group = {
|
||||
.attrs = nct7802_auto_point_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *nct7802_groups[] = {
|
||||
&nct7802_temp_group,
|
||||
&nct7802_in_group,
|
||||
&nct7802_fan_group,
|
||||
&nct7802_pwm_group,
|
||||
&nct7802_auto_point_group,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -776,7 +1066,8 @@ static int nct7802_detect(struct i2c_client *client,
|
||||
|
||||
static bool nct7802_regmap_is_volatile(struct device *dev, unsigned int reg)
|
||||
{
|
||||
return reg != REG_BANK && reg <= 0x20;
|
||||
return (reg != REG_BANK && reg <= 0x20) ||
|
||||
(reg >= REG_PWM(0) && reg <= REG_PWM(2));
|
||||
}
|
||||
|
||||
static const struct regmap_config nct7802_regmap_config = {
|
||||
|
||||
@@ -20,7 +20,8 @@ config SENSORS_PMBUS
|
||||
help
|
||||
If you say yes here you get hardware monitoring support for generic
|
||||
PMBus devices, including but not limited to ADP4000, BMR453, BMR454,
|
||||
MDT040, NCP4200, NCP4208, PDT003, PDT006, PDT012, UDT020, and TPS40400.
|
||||
MDT040, NCP4200, NCP4208, PDT003, PDT006, PDT012, TPS40400, TPS544B20,
|
||||
TPS544B25, TPS544C20, TPS544C25, and UDT020.
|
||||
|
||||
This driver can also be built as a module. If so, the module will
|
||||
be called pmbus.
|
||||
@@ -30,8 +31,8 @@ config SENSORS_ADM1275
|
||||
default n
|
||||
help
|
||||
If you say yes here you get hardware monitoring support for Analog
|
||||
Devices ADM1075, ADM1275, and ADM1276 Hot-Swap Controller and Digital
|
||||
Power Monitors.
|
||||
Devices ADM1075, ADM1275, ADM1276, ADM1293, and ADM1294 Hot-Swap
|
||||
Controller and Digital Power Monitors.
|
||||
|
||||
This driver can also be built as a module. If so, the module will
|
||||
be called adm1275.
|
||||
@@ -51,7 +52,8 @@ config SENSORS_LTC2978
|
||||
default n
|
||||
help
|
||||
If you say yes here you get hardware monitoring support for Linear
|
||||
Technology LTC2974, LTC2977, LTC2978, LTC3880, LTC3883, and LTM4676.
|
||||
Technology LTC2974, LTC2975, LTC2977, LTC2978, LTC2980, LTC3880,
|
||||
LTC3883, LTC3886, LTC3887, LTCM2987, LTM4675, and LTM4676.
|
||||
|
||||
This driver can also be built as a module. If so, the module will
|
||||
be called ltc2978.
|
||||
@@ -73,6 +75,16 @@ config SENSORS_MAX16064
|
||||
This driver can also be built as a module. If so, the module will
|
||||
be called max16064.
|
||||
|
||||
config SENSORS_MAX20751
|
||||
tristate "Maxim MAX20751"
|
||||
default n
|
||||
help
|
||||
If you say yes here you get hardware monitoring support for Maxim
|
||||
MAX20751.
|
||||
|
||||
This driver can also be built as a module. If so, the module will
|
||||
be called max20751.
|
||||
|
||||
config SENSORS_MAX34440
|
||||
tristate "Maxim MAX34440 and compatibles"
|
||||
default n
|
||||
|
||||
@@ -8,6 +8,7 @@ obj-$(CONFIG_SENSORS_ADM1275) += adm1275.o
|
||||
obj-$(CONFIG_SENSORS_LM25066) += lm25066.o
|
||||
obj-$(CONFIG_SENSORS_LTC2978) += ltc2978.o
|
||||
obj-$(CONFIG_SENSORS_MAX16064) += max16064.o
|
||||
obj-$(CONFIG_SENSORS_MAX20751) += max20751.o
|
||||
obj-$(CONFIG_SENSORS_MAX34440) += max34440.o
|
||||
obj-$(CONFIG_SENSORS_MAX8688) += max8688.o
|
||||
obj-$(CONFIG_SENSORS_TPS40422) += tps40422.o
|
||||
|
||||
+260
-100
@@ -21,46 +21,120 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/bitops.h>
|
||||
#include "pmbus.h"
|
||||
|
||||
enum chips { adm1075, adm1275, adm1276 };
|
||||
enum chips { adm1075, adm1275, adm1276, adm1293, adm1294 };
|
||||
|
||||
#define ADM1275_MFR_STATUS_IOUT_WARN2 BIT(0)
|
||||
#define ADM1293_MFR_STATUS_VAUX_UV_WARN BIT(5)
|
||||
#define ADM1293_MFR_STATUS_VAUX_OV_WARN BIT(6)
|
||||
|
||||
#define ADM1275_PEAK_IOUT 0xd0
|
||||
#define ADM1275_PEAK_VIN 0xd1
|
||||
#define ADM1275_PEAK_VOUT 0xd2
|
||||
#define ADM1275_PMON_CONFIG 0xd4
|
||||
|
||||
#define ADM1275_VIN_VOUT_SELECT (1 << 6)
|
||||
#define ADM1275_VRANGE (1 << 5)
|
||||
#define ADM1075_IRANGE_50 (1 << 4)
|
||||
#define ADM1075_IRANGE_25 (1 << 3)
|
||||
#define ADM1075_IRANGE_MASK ((1 << 3) | (1 << 4))
|
||||
#define ADM1275_VIN_VOUT_SELECT BIT(6)
|
||||
#define ADM1275_VRANGE BIT(5)
|
||||
#define ADM1075_IRANGE_50 BIT(4)
|
||||
#define ADM1075_IRANGE_25 BIT(3)
|
||||
#define ADM1075_IRANGE_MASK (BIT(3) | BIT(4))
|
||||
|
||||
#define ADM1293_IRANGE_25 0
|
||||
#define ADM1293_IRANGE_50 BIT(6)
|
||||
#define ADM1293_IRANGE_100 BIT(7)
|
||||
#define ADM1293_IRANGE_200 (BIT(6) | BIT(7))
|
||||
#define ADM1293_IRANGE_MASK (BIT(6) | BIT(7))
|
||||
|
||||
#define ADM1293_VIN_SEL_012 BIT(2)
|
||||
#define ADM1293_VIN_SEL_074 BIT(3)
|
||||
#define ADM1293_VIN_SEL_210 (BIT(2) | BIT(3))
|
||||
#define ADM1293_VIN_SEL_MASK (BIT(2) | BIT(3))
|
||||
|
||||
#define ADM1293_VAUX_EN BIT(1)
|
||||
|
||||
#define ADM1275_IOUT_WARN2_LIMIT 0xd7
|
||||
#define ADM1275_DEVICE_CONFIG 0xd8
|
||||
|
||||
#define ADM1275_IOUT_WARN2_SELECT (1 << 4)
|
||||
#define ADM1275_IOUT_WARN2_SELECT BIT(4)
|
||||
|
||||
#define ADM1276_PEAK_PIN 0xda
|
||||
|
||||
#define ADM1275_MFR_STATUS_IOUT_WARN2 (1 << 0)
|
||||
|
||||
#define ADM1075_READ_VAUX 0xdd
|
||||
#define ADM1075_VAUX_OV_WARN_LIMIT 0xde
|
||||
#define ADM1075_VAUX_UV_WARN_LIMIT 0xdf
|
||||
#define ADM1293_IOUT_MIN 0xe3
|
||||
#define ADM1293_PIN_MIN 0xe4
|
||||
#define ADM1075_VAUX_STATUS 0xf6
|
||||
|
||||
#define ADM1075_VAUX_OV_WARN (1<<7)
|
||||
#define ADM1075_VAUX_UV_WARN (1<<6)
|
||||
#define ADM1075_VAUX_OV_WARN BIT(7)
|
||||
#define ADM1075_VAUX_UV_WARN BIT(6)
|
||||
|
||||
struct adm1275_data {
|
||||
int id;
|
||||
bool have_oc_fault;
|
||||
bool have_uc_fault;
|
||||
bool have_vout;
|
||||
bool have_vaux_status;
|
||||
bool have_mfr_vaux_status;
|
||||
bool have_iout_min;
|
||||
bool have_pin_min;
|
||||
bool have_pin_max;
|
||||
struct pmbus_driver_info info;
|
||||
};
|
||||
|
||||
#define to_adm1275_data(x) container_of(x, struct adm1275_data, info)
|
||||
|
||||
struct coefficients {
|
||||
s16 m;
|
||||
s16 b;
|
||||
s16 R;
|
||||
};
|
||||
|
||||
static const struct coefficients adm1075_coefficients[] = {
|
||||
[0] = { 27169, 0, -1 }, /* voltage */
|
||||
[1] = { 806, 20475, -1 }, /* current, irange25 */
|
||||
[2] = { 404, 20475, -1 }, /* current, irange50 */
|
||||
[3] = { 0, -1, 8549 }, /* power, irange25 */
|
||||
[4] = { 0, -1, 4279 }, /* power, irange50 */
|
||||
};
|
||||
|
||||
static const struct coefficients adm1275_coefficients[] = {
|
||||
[0] = { 19199, 0, -2 }, /* voltage, vrange set */
|
||||
[1] = { 6720, 0, -1 }, /* voltage, vrange not set */
|
||||
[2] = { 807, 20475, -1 }, /* current */
|
||||
};
|
||||
|
||||
static const struct coefficients adm1276_coefficients[] = {
|
||||
[0] = { 19199, 0, -2 }, /* voltage, vrange set */
|
||||
[1] = { 6720, 0, -1 }, /* voltage, vrange not set */
|
||||
[2] = { 807, 20475, -1 }, /* current */
|
||||
[3] = { 6043, 0, -2 }, /* power, vrange set */
|
||||
[4] = { 2115, 0, -1 }, /* power, vrange not set */
|
||||
};
|
||||
|
||||
static const struct coefficients adm1293_coefficients[] = {
|
||||
[0] = { 3333, -1, 0 }, /* voltage, vrange 1.2V */
|
||||
[1] = { 5552, -5, -1 }, /* voltage, vrange 7.4V */
|
||||
[2] = { 19604, -50, -2 }, /* voltage, vrange 21V */
|
||||
[3] = { 8000, -100, -2 }, /* current, irange25 */
|
||||
[4] = { 4000, -100, -2 }, /* current, irange50 */
|
||||
[5] = { 20000, -1000, -3 }, /* current, irange100 */
|
||||
[6] = { 10000, -1000, -3 }, /* current, irange200 */
|
||||
[7] = { 10417, 0, -1 }, /* power, 1.2V, irange25 */
|
||||
[8] = { 5208, 0, -1 }, /* power, 1.2V, irange50 */
|
||||
[9] = { 26042, 0, -2 }, /* power, 1.2V, irange100 */
|
||||
[10] = { 13021, 0, -2 }, /* power, 1.2V, irange200 */
|
||||
[11] = { 17351, 0, -2 }, /* power, 7.4V, irange25 */
|
||||
[12] = { 8676, 0, -2 }, /* power, 7.4V, irange50 */
|
||||
[13] = { 4338, 0, -2 }, /* power, 7.4V, irange100 */
|
||||
[14] = { 21689, 0, -3 }, /* power, 7.4V, irange200 */
|
||||
[15] = { 6126, 0, -2 }, /* power, 21V, irange25 */
|
||||
[16] = { 30631, 0, -3 }, /* power, 21V, irange50 */
|
||||
[17] = { 15316, 0, -3 }, /* power, 21V, irange100 */
|
||||
[18] = { 7658, 0, -3 }, /* power, 21V, irange200 */
|
||||
};
|
||||
|
||||
static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
|
||||
{
|
||||
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
|
||||
@@ -72,42 +146,37 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
|
||||
|
||||
switch (reg) {
|
||||
case PMBUS_IOUT_UC_FAULT_LIMIT:
|
||||
if (data->have_oc_fault) {
|
||||
ret = -ENXIO;
|
||||
break;
|
||||
}
|
||||
if (!data->have_uc_fault)
|
||||
return -ENXIO;
|
||||
ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT);
|
||||
break;
|
||||
case PMBUS_IOUT_OC_FAULT_LIMIT:
|
||||
if (!data->have_oc_fault) {
|
||||
ret = -ENXIO;
|
||||
break;
|
||||
}
|
||||
if (!data->have_oc_fault)
|
||||
return -ENXIO;
|
||||
ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT);
|
||||
break;
|
||||
case PMBUS_VOUT_OV_WARN_LIMIT:
|
||||
if (data->id != adm1075) {
|
||||
ret = -ENODATA;
|
||||
break;
|
||||
}
|
||||
if (data->have_vout)
|
||||
return -ENODATA;
|
||||
ret = pmbus_read_word_data(client, 0,
|
||||
ADM1075_VAUX_OV_WARN_LIMIT);
|
||||
break;
|
||||
case PMBUS_VOUT_UV_WARN_LIMIT:
|
||||
if (data->id != adm1075) {
|
||||
ret = -ENODATA;
|
||||
break;
|
||||
}
|
||||
if (data->have_vout)
|
||||
return -ENODATA;
|
||||
ret = pmbus_read_word_data(client, 0,
|
||||
ADM1075_VAUX_UV_WARN_LIMIT);
|
||||
break;
|
||||
case PMBUS_READ_VOUT:
|
||||
if (data->id != adm1075) {
|
||||
ret = -ENODATA;
|
||||
break;
|
||||
}
|
||||
if (data->have_vout)
|
||||
return -ENODATA;
|
||||
ret = pmbus_read_word_data(client, 0, ADM1075_READ_VAUX);
|
||||
break;
|
||||
case PMBUS_VIRT_READ_IOUT_MIN:
|
||||
if (!data->have_iout_min)
|
||||
return -ENXIO;
|
||||
ret = pmbus_read_word_data(client, 0, ADM1293_IOUT_MIN);
|
||||
break;
|
||||
case PMBUS_VIRT_READ_IOUT_MAX:
|
||||
ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_IOUT);
|
||||
break;
|
||||
@@ -117,11 +186,14 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
|
||||
case PMBUS_VIRT_READ_VIN_MAX:
|
||||
ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VIN);
|
||||
break;
|
||||
case PMBUS_VIRT_READ_PIN_MIN:
|
||||
if (!data->have_pin_min)
|
||||
return -ENXIO;
|
||||
ret = pmbus_read_word_data(client, 0, ADM1293_PIN_MIN);
|
||||
break;
|
||||
case PMBUS_VIRT_READ_PIN_MAX:
|
||||
if (data->id == adm1275) {
|
||||
ret = -ENXIO;
|
||||
break;
|
||||
}
|
||||
if (!data->have_pin_max)
|
||||
return -ENXIO;
|
||||
ret = pmbus_read_word_data(client, 0, ADM1276_PEAK_PIN);
|
||||
break;
|
||||
case PMBUS_VIRT_RESET_IOUT_HISTORY:
|
||||
@@ -129,8 +201,8 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
|
||||
case PMBUS_VIRT_RESET_VIN_HISTORY:
|
||||
break;
|
||||
case PMBUS_VIRT_RESET_PIN_HISTORY:
|
||||
if (data->id == adm1275)
|
||||
ret = -ENXIO;
|
||||
if (!data->have_pin_max)
|
||||
return -ENXIO;
|
||||
break;
|
||||
default:
|
||||
ret = -ENODATA;
|
||||
@@ -142,6 +214,8 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
|
||||
static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
|
||||
u16 word)
|
||||
{
|
||||
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
|
||||
const struct adm1275_data *data = to_adm1275_data(info);
|
||||
int ret;
|
||||
|
||||
if (page)
|
||||
@@ -155,6 +229,9 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
|
||||
break;
|
||||
case PMBUS_VIRT_RESET_IOUT_HISTORY:
|
||||
ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_IOUT, 0);
|
||||
if (!ret && data->have_iout_min)
|
||||
ret = pmbus_write_word_data(client, 0,
|
||||
ADM1293_IOUT_MIN, 0);
|
||||
break;
|
||||
case PMBUS_VIRT_RESET_VOUT_HISTORY:
|
||||
ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VOUT, 0);
|
||||
@@ -164,6 +241,9 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
|
||||
break;
|
||||
case PMBUS_VIRT_RESET_PIN_HISTORY:
|
||||
ret = pmbus_write_word_data(client, 0, ADM1276_PEAK_PIN, 0);
|
||||
if (!ret && data->have_pin_min)
|
||||
ret = pmbus_write_word_data(client, 0,
|
||||
ADM1293_PIN_MIN, 0);
|
||||
break;
|
||||
default:
|
||||
ret = -ENODATA;
|
||||
@@ -186,29 +266,40 @@ static int adm1275_read_byte_data(struct i2c_client *client, int page, int reg)
|
||||
ret = pmbus_read_byte_data(client, page, PMBUS_STATUS_IOUT);
|
||||
if (ret < 0)
|
||||
break;
|
||||
if (!data->have_oc_fault && !data->have_uc_fault)
|
||||
break;
|
||||
mfr_status = pmbus_read_byte_data(client, page,
|
||||
PMBUS_STATUS_MFR_SPECIFIC);
|
||||
if (mfr_status < 0) {
|
||||
ret = mfr_status;
|
||||
break;
|
||||
}
|
||||
if (mfr_status < 0)
|
||||
return mfr_status;
|
||||
if (mfr_status & ADM1275_MFR_STATUS_IOUT_WARN2) {
|
||||
ret |= data->have_oc_fault ?
|
||||
PB_IOUT_OC_FAULT : PB_IOUT_UC_FAULT;
|
||||
}
|
||||
break;
|
||||
case PMBUS_STATUS_VOUT:
|
||||
if (data->id != adm1075) {
|
||||
ret = -ENODATA;
|
||||
break;
|
||||
}
|
||||
if (data->have_vout)
|
||||
return -ENODATA;
|
||||
ret = 0;
|
||||
mfr_status = pmbus_read_byte_data(client, 0,
|
||||
ADM1075_VAUX_STATUS);
|
||||
if (mfr_status & ADM1075_VAUX_OV_WARN)
|
||||
ret |= PB_VOLTAGE_OV_WARNING;
|
||||
if (mfr_status & ADM1075_VAUX_UV_WARN)
|
||||
ret |= PB_VOLTAGE_UV_WARNING;
|
||||
if (data->have_vaux_status) {
|
||||
mfr_status = pmbus_read_byte_data(client, 0,
|
||||
ADM1075_VAUX_STATUS);
|
||||
if (mfr_status < 0)
|
||||
return mfr_status;
|
||||
if (mfr_status & ADM1075_VAUX_OV_WARN)
|
||||
ret |= PB_VOLTAGE_OV_WARNING;
|
||||
if (mfr_status & ADM1075_VAUX_UV_WARN)
|
||||
ret |= PB_VOLTAGE_UV_WARNING;
|
||||
} else if (data->have_mfr_vaux_status) {
|
||||
mfr_status = pmbus_read_byte_data(client, page,
|
||||
PMBUS_STATUS_MFR_SPECIFIC);
|
||||
if (mfr_status < 0)
|
||||
return mfr_status;
|
||||
if (mfr_status & ADM1293_MFR_STATUS_VAUX_OV_WARN)
|
||||
ret |= PB_VOLTAGE_OV_WARNING;
|
||||
if (mfr_status & ADM1293_MFR_STATUS_VAUX_UV_WARN)
|
||||
ret |= PB_VOLTAGE_UV_WARNING;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = -ENODATA;
|
||||
@@ -221,6 +312,8 @@ static const struct i2c_device_id adm1275_id[] = {
|
||||
{ "adm1075", adm1075 },
|
||||
{ "adm1275", adm1275 },
|
||||
{ "adm1276", adm1276 },
|
||||
{ "adm1293", adm1293 },
|
||||
{ "adm1294", adm1294 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, adm1275_id);
|
||||
@@ -234,6 +327,8 @@ static int adm1275_probe(struct i2c_client *client,
|
||||
struct pmbus_driver_info *info;
|
||||
struct adm1275_data *data;
|
||||
const struct i2c_device_id *mid;
|
||||
const struct coefficients *coefficients;
|
||||
int vindex = -1, voindex = -1, cindex = -1, pindex = -1;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_SMBUS_READ_BYTE_DATA
|
||||
@@ -290,61 +385,38 @@ static int adm1275_probe(struct i2c_client *client,
|
||||
info->format[PSC_VOLTAGE_IN] = direct;
|
||||
info->format[PSC_VOLTAGE_OUT] = direct;
|
||||
info->format[PSC_CURRENT_OUT] = direct;
|
||||
info->m[PSC_CURRENT_OUT] = 807;
|
||||
info->b[PSC_CURRENT_OUT] = 20475;
|
||||
info->R[PSC_CURRENT_OUT] = -1;
|
||||
info->format[PSC_POWER] = direct;
|
||||
info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
|
||||
|
||||
info->read_word_data = adm1275_read_word_data;
|
||||
info->read_byte_data = adm1275_read_byte_data;
|
||||
info->write_word_data = adm1275_write_word_data;
|
||||
|
||||
if (data->id == adm1075) {
|
||||
info->m[PSC_VOLTAGE_IN] = 27169;
|
||||
info->b[PSC_VOLTAGE_IN] = 0;
|
||||
info->R[PSC_VOLTAGE_IN] = -1;
|
||||
info->m[PSC_VOLTAGE_OUT] = 27169;
|
||||
info->b[PSC_VOLTAGE_OUT] = 0;
|
||||
info->R[PSC_VOLTAGE_OUT] = -1;
|
||||
} else if (config & ADM1275_VRANGE) {
|
||||
info->m[PSC_VOLTAGE_IN] = 19199;
|
||||
info->b[PSC_VOLTAGE_IN] = 0;
|
||||
info->R[PSC_VOLTAGE_IN] = -2;
|
||||
info->m[PSC_VOLTAGE_OUT] = 19199;
|
||||
info->b[PSC_VOLTAGE_OUT] = 0;
|
||||
info->R[PSC_VOLTAGE_OUT] = -2;
|
||||
} else {
|
||||
info->m[PSC_VOLTAGE_IN] = 6720;
|
||||
info->b[PSC_VOLTAGE_IN] = 0;
|
||||
info->R[PSC_VOLTAGE_IN] = -1;
|
||||
info->m[PSC_VOLTAGE_OUT] = 6720;
|
||||
info->b[PSC_VOLTAGE_OUT] = 0;
|
||||
info->R[PSC_VOLTAGE_OUT] = -1;
|
||||
}
|
||||
|
||||
if (device_config & ADM1275_IOUT_WARN2_SELECT)
|
||||
data->have_oc_fault = true;
|
||||
|
||||
switch (data->id) {
|
||||
case adm1075:
|
||||
info->format[PSC_POWER] = direct;
|
||||
info->b[PSC_POWER] = 0;
|
||||
info->R[PSC_POWER] = -1;
|
||||
if (device_config & ADM1275_IOUT_WARN2_SELECT)
|
||||
data->have_oc_fault = true;
|
||||
else
|
||||
data->have_uc_fault = true;
|
||||
data->have_pin_max = true;
|
||||
data->have_vaux_status = true;
|
||||
|
||||
coefficients = adm1075_coefficients;
|
||||
vindex = 0;
|
||||
switch (config & ADM1075_IRANGE_MASK) {
|
||||
case ADM1075_IRANGE_25:
|
||||
info->m[PSC_POWER] = 8549;
|
||||
info->m[PSC_CURRENT_OUT] = 806;
|
||||
cindex = 1;
|
||||
pindex = 3;
|
||||
break;
|
||||
case ADM1075_IRANGE_50:
|
||||
info->m[PSC_POWER] = 4279;
|
||||
info->m[PSC_CURRENT_OUT] = 404;
|
||||
cindex = 2;
|
||||
pindex = 4;
|
||||
break;
|
||||
default:
|
||||
dev_err(&client->dev, "Invalid input current range");
|
||||
info->m[PSC_POWER] = 0;
|
||||
info->m[PSC_CURRENT_OUT] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_PIN
|
||||
| PMBUS_HAVE_STATUS_INPUT;
|
||||
if (config & ADM1275_VIN_VOUT_SELECT)
|
||||
@@ -352,6 +424,16 @@ static int adm1275_probe(struct i2c_client *client,
|
||||
PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
|
||||
break;
|
||||
case adm1275:
|
||||
if (device_config & ADM1275_IOUT_WARN2_SELECT)
|
||||
data->have_oc_fault = true;
|
||||
else
|
||||
data->have_uc_fault = true;
|
||||
data->have_vout = true;
|
||||
|
||||
coefficients = adm1275_coefficients;
|
||||
vindex = (config & ADM1275_VRANGE) ? 0 : 1;
|
||||
cindex = 2;
|
||||
|
||||
if (config & ADM1275_VIN_VOUT_SELECT)
|
||||
info->func[0] |=
|
||||
PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
|
||||
@@ -360,22 +442,100 @@ static int adm1275_probe(struct i2c_client *client,
|
||||
PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT;
|
||||
break;
|
||||
case adm1276:
|
||||
info->format[PSC_POWER] = direct;
|
||||
if (device_config & ADM1275_IOUT_WARN2_SELECT)
|
||||
data->have_oc_fault = true;
|
||||
else
|
||||
data->have_uc_fault = true;
|
||||
data->have_vout = true;
|
||||
data->have_pin_max = true;
|
||||
|
||||
coefficients = adm1276_coefficients;
|
||||
vindex = (config & ADM1275_VRANGE) ? 0 : 1;
|
||||
cindex = 2;
|
||||
pindex = (config & ADM1275_VRANGE) ? 3 : 4;
|
||||
|
||||
info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_PIN
|
||||
| PMBUS_HAVE_STATUS_INPUT;
|
||||
if (config & ADM1275_VIN_VOUT_SELECT)
|
||||
info->func[0] |=
|
||||
PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
|
||||
if (config & ADM1275_VRANGE) {
|
||||
info->m[PSC_POWER] = 6043;
|
||||
info->b[PSC_POWER] = 0;
|
||||
info->R[PSC_POWER] = -2;
|
||||
} else {
|
||||
info->m[PSC_POWER] = 2115;
|
||||
info->b[PSC_POWER] = 0;
|
||||
info->R[PSC_POWER] = -1;
|
||||
}
|
||||
break;
|
||||
case adm1293:
|
||||
case adm1294:
|
||||
data->have_iout_min = true;
|
||||
data->have_pin_min = true;
|
||||
data->have_pin_max = true;
|
||||
data->have_mfr_vaux_status = true;
|
||||
|
||||
coefficients = adm1293_coefficients;
|
||||
|
||||
voindex = 0;
|
||||
switch (config & ADM1293_VIN_SEL_MASK) {
|
||||
case ADM1293_VIN_SEL_012: /* 1.2V */
|
||||
vindex = 0;
|
||||
break;
|
||||
case ADM1293_VIN_SEL_074: /* 7.4V */
|
||||
vindex = 1;
|
||||
break;
|
||||
case ADM1293_VIN_SEL_210: /* 21V */
|
||||
vindex = 2;
|
||||
break;
|
||||
default: /* disabled */
|
||||
break;
|
||||
}
|
||||
|
||||
switch (config & ADM1293_IRANGE_MASK) {
|
||||
case ADM1293_IRANGE_25:
|
||||
cindex = 3;
|
||||
break;
|
||||
case ADM1293_IRANGE_50:
|
||||
cindex = 4;
|
||||
break;
|
||||
case ADM1293_IRANGE_100:
|
||||
cindex = 5;
|
||||
break;
|
||||
case ADM1293_IRANGE_200:
|
||||
cindex = 6;
|
||||
break;
|
||||
}
|
||||
|
||||
if (vindex >= 0)
|
||||
pindex = 7 + vindex * 4 + (cindex - 3);
|
||||
|
||||
if (config & ADM1293_VAUX_EN)
|
||||
info->func[0] |=
|
||||
PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
|
||||
|
||||
info->func[0] |= PMBUS_HAVE_PIN |
|
||||
PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT;
|
||||
|
||||
break;
|
||||
default:
|
||||
dev_err(&client->dev, "Unsupported device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (voindex < 0)
|
||||
voindex = vindex;
|
||||
if (vindex >= 0) {
|
||||
info->m[PSC_VOLTAGE_IN] = coefficients[vindex].m;
|
||||
info->b[PSC_VOLTAGE_IN] = coefficients[vindex].b;
|
||||
info->R[PSC_VOLTAGE_IN] = coefficients[vindex].R;
|
||||
}
|
||||
if (voindex >= 0) {
|
||||
info->m[PSC_VOLTAGE_OUT] = coefficients[voindex].m;
|
||||
info->b[PSC_VOLTAGE_OUT] = coefficients[voindex].b;
|
||||
info->R[PSC_VOLTAGE_OUT] = coefficients[voindex].R;
|
||||
}
|
||||
if (cindex >= 0) {
|
||||
info->m[PSC_CURRENT_OUT] = coefficients[cindex].m;
|
||||
info->b[PSC_CURRENT_OUT] = coefficients[cindex].b;
|
||||
info->R[PSC_CURRENT_OUT] = coefficients[cindex].R;
|
||||
}
|
||||
if (pindex >= 0) {
|
||||
info->m[PSC_POWER] = coefficients[pindex].m;
|
||||
info->b[PSC_POWER] = coefficients[pindex].b;
|
||||
info->R[PSC_POWER] = coefficients[pindex].R;
|
||||
}
|
||||
|
||||
return pmbus_do_probe(client, id, info);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
@@ -42,15 +43,15 @@ enum chips { lm25056, lm25063, lm25066, lm5064, lm5066 };
|
||||
#define LM25066_READ_AVG_IIN 0xde
|
||||
#define LM25066_READ_AVG_PIN 0xdf
|
||||
|
||||
#define LM25066_DEV_SETUP_CL (1 << 4) /* Current limit */
|
||||
#define LM25066_DEV_SETUP_CL BIT(4) /* Current limit */
|
||||
|
||||
/* LM25056 only */
|
||||
|
||||
#define LM25056_VAUX_OV_WARN_LIMIT 0xe3
|
||||
#define LM25056_VAUX_UV_WARN_LIMIT 0xe4
|
||||
|
||||
#define LM25056_MFR_STS_VAUX_OV_WARN (1 << 1)
|
||||
#define LM25056_MFR_STS_VAUX_UV_WARN (1 << 0)
|
||||
#define LM25056_MFR_STS_VAUX_OV_WARN BIT(1)
|
||||
#define LM25056_MFR_STS_VAUX_UV_WARN BIT(0)
|
||||
|
||||
/* LM25063 only */
|
||||
|
||||
|
||||
+365
-117
@@ -1,9 +1,9 @@
|
||||
/*
|
||||
* Hardware monitoring driver for LTC2974, LTC2977, LTC2978, LTC3880,
|
||||
* LTC3883, and LTM4676
|
||||
* Hardware monitoring driver for LTC2978 and compatible chips.
|
||||
*
|
||||
* Copyright (c) 2011 Ericsson AB.
|
||||
* Copyright (c) 2013, 2014 Guenter Roeck
|
||||
* Copyright (c) 2013, 2014, 2015 Guenter Roeck
|
||||
* Copyright (c) 2015 Linear Technology
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,6 +16,8 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
@@ -25,49 +27,71 @@
|
||||
#include <linux/regulator/driver.h>
|
||||
#include "pmbus.h"
|
||||
|
||||
enum chips { ltc2974, ltc2977, ltc2978, ltc3880, ltc3883, ltm4676 };
|
||||
enum chips { ltc2974, ltc2975, ltc2977, ltc2978, ltc2980, ltc3880, ltc3882,
|
||||
ltc3883, ltc3886, ltc3887, ltm2987, ltm4675, ltm4676 };
|
||||
|
||||
/* Common for all chips */
|
||||
#define LTC2978_MFR_VOUT_PEAK 0xdd
|
||||
#define LTC2978_MFR_VIN_PEAK 0xde
|
||||
#define LTC2978_MFR_TEMPERATURE_PEAK 0xdf
|
||||
#define LTC2978_MFR_SPECIAL_ID 0xe7
|
||||
#define LTC2978_MFR_SPECIAL_ID 0xe7 /* Undocumented on LTC3882 */
|
||||
#define LTC2978_MFR_COMMON 0xef
|
||||
|
||||
/* LTC2974, LCT2977, and LTC2978 */
|
||||
/* LTC2974, LTC2975, LCT2977, LTC2980, LTC2978, and LTM2987 */
|
||||
#define LTC2978_MFR_VOUT_MIN 0xfb
|
||||
#define LTC2978_MFR_VIN_MIN 0xfc
|
||||
#define LTC2978_MFR_TEMPERATURE_MIN 0xfd
|
||||
|
||||
/* LTC2974 only */
|
||||
/* LTC2974, LTC2975 */
|
||||
#define LTC2974_MFR_IOUT_PEAK 0xd7
|
||||
#define LTC2974_MFR_IOUT_MIN 0xd8
|
||||
|
||||
/* LTC3880, LTC3883, and LTM4676 */
|
||||
/* LTC3880, LTC3882, LTC3883, LTC3887, LTM4675, and LTM4676 */
|
||||
#define LTC3880_MFR_IOUT_PEAK 0xd7
|
||||
#define LTC3880_MFR_CLEAR_PEAKS 0xe3
|
||||
#define LTC3880_MFR_TEMPERATURE2_PEAK 0xf4
|
||||
|
||||
/* LTC3883 only */
|
||||
/* LTC3883 and LTC3886 only */
|
||||
#define LTC3883_MFR_IIN_PEAK 0xe1
|
||||
|
||||
#define LTC2974_ID_REV1 0x0212
|
||||
#define LTC2974_ID_REV2 0x0213
|
||||
/* LTC2975 only */
|
||||
#define LTC2975_MFR_IIN_PEAK 0xc4
|
||||
#define LTC2975_MFR_IIN_MIN 0xc5
|
||||
#define LTC2975_MFR_PIN_PEAK 0xc6
|
||||
#define LTC2975_MFR_PIN_MIN 0xc7
|
||||
|
||||
#define LTC2978_ID_MASK 0xfff0
|
||||
|
||||
#define LTC2974_ID 0x0210
|
||||
#define LTC2975_ID 0x0220
|
||||
#define LTC2977_ID 0x0130
|
||||
#define LTC2978_ID_REV1 0x0121
|
||||
#define LTC2978_ID_REV2 0x0122
|
||||
#define LTC2978A_ID 0x0124
|
||||
#define LTC3880_ID 0x4000
|
||||
#define LTC3880_ID_MASK 0xff00
|
||||
#define LTC2978_ID_REV1 0x0110 /* Early revision */
|
||||
#define LTC2978_ID_REV2 0x0120
|
||||
#define LTC2980_ID_A 0x8030 /* A/B for two die IDs */
|
||||
#define LTC2980_ID_B 0x8040
|
||||
#define LTC3880_ID 0x4020
|
||||
#define LTC3882_ID 0x4200
|
||||
#define LTC3882_ID_D1 0x4240 /* Dash 1 */
|
||||
#define LTC3883_ID 0x4300
|
||||
#define LTC3883_ID_MASK 0xff00
|
||||
#define LTM4676_ID 0x4480 /* datasheet claims 0x440X */
|
||||
#define LTM4676_ID_MASK 0xfff0
|
||||
#define LTC3886_ID 0x4600
|
||||
#define LTC3887_ID 0x4700
|
||||
#define LTM2987_ID_A 0x8010 /* A/B for two die IDs */
|
||||
#define LTM2987_ID_B 0x8020
|
||||
#define LTM4675_ID 0x47a0
|
||||
#define LTM4676_ID_REV1 0x4400
|
||||
#define LTM4676_ID_REV2 0x4480
|
||||
#define LTM4676A_ID 0x47e0
|
||||
|
||||
#define LTC2974_NUM_PAGES 4
|
||||
#define LTC2978_NUM_PAGES 8
|
||||
#define LTC3880_NUM_PAGES 2
|
||||
#define LTC3883_NUM_PAGES 1
|
||||
|
||||
#define LTC_POLL_TIMEOUT 100 /* in milli-seconds */
|
||||
|
||||
#define LTC_NOT_BUSY BIT(5)
|
||||
#define LTC_NOT_PENDING BIT(4)
|
||||
|
||||
/*
|
||||
* LTC2978 clears peak data whenever the CLEAR_FAULTS command is executed, which
|
||||
* happens pretty much each time chip data is updated. Raw peak data therefore
|
||||
@@ -82,13 +106,91 @@ struct ltc2978_data {
|
||||
u16 temp_min[LTC2974_NUM_PAGES], temp_max[LTC2974_NUM_PAGES];
|
||||
u16 vout_min[LTC2978_NUM_PAGES], vout_max[LTC2978_NUM_PAGES];
|
||||
u16 iout_min[LTC2974_NUM_PAGES], iout_max[LTC2974_NUM_PAGES];
|
||||
u16 iin_max;
|
||||
u16 iin_min, iin_max;
|
||||
u16 pin_min, pin_max;
|
||||
u16 temp2_max;
|
||||
struct pmbus_driver_info info;
|
||||
u32 features;
|
||||
};
|
||||
|
||||
#define to_ltc2978_data(x) container_of(x, struct ltc2978_data, info)
|
||||
|
||||
#define FEAT_CLEAR_PEAKS BIT(0)
|
||||
#define FEAT_NEEDS_POLLING BIT(1)
|
||||
|
||||
#define has_clear_peaks(d) ((d)->features & FEAT_CLEAR_PEAKS)
|
||||
#define needs_polling(d) ((d)->features & FEAT_NEEDS_POLLING)
|
||||
|
||||
static int ltc_wait_ready(struct i2c_client *client)
|
||||
{
|
||||
unsigned long timeout = jiffies + msecs_to_jiffies(LTC_POLL_TIMEOUT);
|
||||
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
|
||||
struct ltc2978_data *data = to_ltc2978_data(info);
|
||||
int status;
|
||||
u8 mask;
|
||||
|
||||
if (!needs_polling(data))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* LTC3883 does not support LTC_NOT_PENDING, even though
|
||||
* the datasheet claims that it does.
|
||||
*/
|
||||
mask = LTC_NOT_BUSY;
|
||||
if (data->id != ltc3883)
|
||||
mask |= LTC_NOT_PENDING;
|
||||
|
||||
do {
|
||||
status = pmbus_read_byte_data(client, 0, LTC2978_MFR_COMMON);
|
||||
if (status == -EBADMSG || status == -ENXIO) {
|
||||
/* PEC error or NACK: chip may be busy, try again */
|
||||
usleep_range(50, 100);
|
||||
continue;
|
||||
}
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
if ((status & mask) == mask)
|
||||
return 0;
|
||||
|
||||
usleep_range(50, 100);
|
||||
} while (time_before(jiffies, timeout));
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int ltc_read_word_data(struct i2c_client *client, int page, int reg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ltc_wait_ready(client);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return pmbus_read_word_data(client, page, reg);
|
||||
}
|
||||
|
||||
static int ltc_read_byte_data(struct i2c_client *client, int page, int reg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ltc_wait_ready(client);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return pmbus_read_byte_data(client, page, reg);
|
||||
}
|
||||
|
||||
static int ltc_write_byte(struct i2c_client *client, int page, u8 byte)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ltc_wait_ready(client);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return pmbus_write_byte(client, page, byte);
|
||||
}
|
||||
|
||||
static inline int lin11_to_val(int data)
|
||||
{
|
||||
s16 e = ((s16)data) >> 11;
|
||||
@@ -102,6 +204,34 @@ static inline int lin11_to_val(int data)
|
||||
return (e < 0 ? m >> -e : m << e);
|
||||
}
|
||||
|
||||
static int ltc_get_max(struct ltc2978_data *data, struct i2c_client *client,
|
||||
int page, int reg, u16 *pmax)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ltc_read_word_data(client, page, reg);
|
||||
if (ret >= 0) {
|
||||
if (lin11_to_val(ret) > lin11_to_val(*pmax))
|
||||
*pmax = ret;
|
||||
ret = *pmax;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ltc_get_min(struct ltc2978_data *data, struct i2c_client *client,
|
||||
int page, int reg, u16 *pmin)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ltc_read_word_data(client, page, reg);
|
||||
if (ret >= 0) {
|
||||
if (lin11_to_val(ret) < lin11_to_val(*pmin))
|
||||
*pmin = ret;
|
||||
ret = *pmin;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ltc2978_read_word_data_common(struct i2c_client *client, int page,
|
||||
int reg)
|
||||
{
|
||||
@@ -111,15 +241,11 @@ static int ltc2978_read_word_data_common(struct i2c_client *client, int page,
|
||||
|
||||
switch (reg) {
|
||||
case PMBUS_VIRT_READ_VIN_MAX:
|
||||
ret = pmbus_read_word_data(client, page, LTC2978_MFR_VIN_PEAK);
|
||||
if (ret >= 0) {
|
||||
if (lin11_to_val(ret) > lin11_to_val(data->vin_max))
|
||||
data->vin_max = ret;
|
||||
ret = data->vin_max;
|
||||
}
|
||||
ret = ltc_get_max(data, client, page, LTC2978_MFR_VIN_PEAK,
|
||||
&data->vin_max);
|
||||
break;
|
||||
case PMBUS_VIRT_READ_VOUT_MAX:
|
||||
ret = pmbus_read_word_data(client, page, LTC2978_MFR_VOUT_PEAK);
|
||||
ret = ltc_read_word_data(client, page, LTC2978_MFR_VOUT_PEAK);
|
||||
if (ret >= 0) {
|
||||
/*
|
||||
* VOUT is 16 bit unsigned with fixed exponent,
|
||||
@@ -131,14 +257,9 @@ static int ltc2978_read_word_data_common(struct i2c_client *client, int page,
|
||||
}
|
||||
break;
|
||||
case PMBUS_VIRT_READ_TEMP_MAX:
|
||||
ret = pmbus_read_word_data(client, page,
|
||||
LTC2978_MFR_TEMPERATURE_PEAK);
|
||||
if (ret >= 0) {
|
||||
if (lin11_to_val(ret)
|
||||
> lin11_to_val(data->temp_max[page]))
|
||||
data->temp_max[page] = ret;
|
||||
ret = data->temp_max[page];
|
||||
}
|
||||
ret = ltc_get_max(data, client, page,
|
||||
LTC2978_MFR_TEMPERATURE_PEAK,
|
||||
&data->temp_max[page]);
|
||||
break;
|
||||
case PMBUS_VIRT_RESET_VOUT_HISTORY:
|
||||
case PMBUS_VIRT_RESET_VIN_HISTORY:
|
||||
@@ -146,6 +267,9 @@ static int ltc2978_read_word_data_common(struct i2c_client *client, int page,
|
||||
ret = 0;
|
||||
break;
|
||||
default:
|
||||
ret = ltc_wait_ready(client);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = -ENODATA;
|
||||
break;
|
||||
}
|
||||
@@ -160,15 +284,11 @@ static int ltc2978_read_word_data(struct i2c_client *client, int page, int reg)
|
||||
|
||||
switch (reg) {
|
||||
case PMBUS_VIRT_READ_VIN_MIN:
|
||||
ret = pmbus_read_word_data(client, page, LTC2978_MFR_VIN_MIN);
|
||||
if (ret >= 0) {
|
||||
if (lin11_to_val(ret) < lin11_to_val(data->vin_min))
|
||||
data->vin_min = ret;
|
||||
ret = data->vin_min;
|
||||
}
|
||||
ret = ltc_get_min(data, client, page, LTC2978_MFR_VIN_MIN,
|
||||
&data->vin_min);
|
||||
break;
|
||||
case PMBUS_VIRT_READ_VOUT_MIN:
|
||||
ret = pmbus_read_word_data(client, page, LTC2978_MFR_VOUT_MIN);
|
||||
ret = ltc_read_word_data(client, page, LTC2978_MFR_VOUT_MIN);
|
||||
if (ret >= 0) {
|
||||
/*
|
||||
* VOUT_MIN is known to not be supported on some lots
|
||||
@@ -184,14 +304,9 @@ static int ltc2978_read_word_data(struct i2c_client *client, int page, int reg)
|
||||
}
|
||||
break;
|
||||
case PMBUS_VIRT_READ_TEMP_MIN:
|
||||
ret = pmbus_read_word_data(client, page,
|
||||
LTC2978_MFR_TEMPERATURE_MIN);
|
||||
if (ret >= 0) {
|
||||
if (lin11_to_val(ret)
|
||||
< lin11_to_val(data->temp_min[page]))
|
||||
data->temp_min[page] = ret;
|
||||
ret = data->temp_min[page];
|
||||
}
|
||||
ret = ltc_get_min(data, client, page,
|
||||
LTC2978_MFR_TEMPERATURE_MIN,
|
||||
&data->temp_min[page]);
|
||||
break;
|
||||
case PMBUS_VIRT_READ_IOUT_MAX:
|
||||
case PMBUS_VIRT_RESET_IOUT_HISTORY:
|
||||
@@ -214,22 +329,12 @@ static int ltc2974_read_word_data(struct i2c_client *client, int page, int reg)
|
||||
|
||||
switch (reg) {
|
||||
case PMBUS_VIRT_READ_IOUT_MAX:
|
||||
ret = pmbus_read_word_data(client, page, LTC2974_MFR_IOUT_PEAK);
|
||||
if (ret >= 0) {
|
||||
if (lin11_to_val(ret)
|
||||
> lin11_to_val(data->iout_max[page]))
|
||||
data->iout_max[page] = ret;
|
||||
ret = data->iout_max[page];
|
||||
}
|
||||
ret = ltc_get_max(data, client, page, LTC2974_MFR_IOUT_PEAK,
|
||||
&data->iout_max[page]);
|
||||
break;
|
||||
case PMBUS_VIRT_READ_IOUT_MIN:
|
||||
ret = pmbus_read_word_data(client, page, LTC2974_MFR_IOUT_MIN);
|
||||
if (ret >= 0) {
|
||||
if (lin11_to_val(ret)
|
||||
< lin11_to_val(data->iout_min[page]))
|
||||
data->iout_min[page] = ret;
|
||||
ret = data->iout_min[page];
|
||||
}
|
||||
ret = ltc_get_min(data, client, page, LTC2974_MFR_IOUT_MIN,
|
||||
&data->iout_min[page]);
|
||||
break;
|
||||
case PMBUS_VIRT_RESET_IOUT_HISTORY:
|
||||
ret = 0;
|
||||
@@ -241,6 +346,40 @@ static int ltc2974_read_word_data(struct i2c_client *client, int page, int reg)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ltc2975_read_word_data(struct i2c_client *client, int page, int reg)
|
||||
{
|
||||
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
|
||||
struct ltc2978_data *data = to_ltc2978_data(info);
|
||||
int ret;
|
||||
|
||||
switch (reg) {
|
||||
case PMBUS_VIRT_READ_IIN_MAX:
|
||||
ret = ltc_get_max(data, client, page, LTC2975_MFR_IIN_PEAK,
|
||||
&data->iin_max);
|
||||
break;
|
||||
case PMBUS_VIRT_READ_IIN_MIN:
|
||||
ret = ltc_get_min(data, client, page, LTC2975_MFR_IIN_MIN,
|
||||
&data->iin_min);
|
||||
break;
|
||||
case PMBUS_VIRT_READ_PIN_MAX:
|
||||
ret = ltc_get_max(data, client, page, LTC2975_MFR_PIN_PEAK,
|
||||
&data->pin_max);
|
||||
break;
|
||||
case PMBUS_VIRT_READ_PIN_MIN:
|
||||
ret = ltc_get_min(data, client, page, LTC2975_MFR_PIN_MIN,
|
||||
&data->pin_min);
|
||||
break;
|
||||
case PMBUS_VIRT_RESET_IIN_HISTORY:
|
||||
case PMBUS_VIRT_RESET_PIN_HISTORY:
|
||||
ret = 0;
|
||||
break;
|
||||
default:
|
||||
ret = ltc2978_read_word_data(client, page, reg);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ltc3880_read_word_data(struct i2c_client *client, int page, int reg)
|
||||
{
|
||||
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
|
||||
@@ -249,22 +388,13 @@ static int ltc3880_read_word_data(struct i2c_client *client, int page, int reg)
|
||||
|
||||
switch (reg) {
|
||||
case PMBUS_VIRT_READ_IOUT_MAX:
|
||||
ret = pmbus_read_word_data(client, page, LTC3880_MFR_IOUT_PEAK);
|
||||
if (ret >= 0) {
|
||||
if (lin11_to_val(ret)
|
||||
> lin11_to_val(data->iout_max[page]))
|
||||
data->iout_max[page] = ret;
|
||||
ret = data->iout_max[page];
|
||||
}
|
||||
ret = ltc_get_max(data, client, page, LTC3880_MFR_IOUT_PEAK,
|
||||
&data->iout_max[page]);
|
||||
break;
|
||||
case PMBUS_VIRT_READ_TEMP2_MAX:
|
||||
ret = pmbus_read_word_data(client, page,
|
||||
LTC3880_MFR_TEMPERATURE2_PEAK);
|
||||
if (ret >= 0) {
|
||||
if (lin11_to_val(ret) > lin11_to_val(data->temp2_max))
|
||||
data->temp2_max = ret;
|
||||
ret = data->temp2_max;
|
||||
}
|
||||
ret = ltc_get_max(data, client, page,
|
||||
LTC3880_MFR_TEMPERATURE2_PEAK,
|
||||
&data->temp2_max);
|
||||
break;
|
||||
case PMBUS_VIRT_READ_VIN_MIN:
|
||||
case PMBUS_VIRT_READ_VOUT_MIN:
|
||||
@@ -290,13 +420,8 @@ static int ltc3883_read_word_data(struct i2c_client *client, int page, int reg)
|
||||
|
||||
switch (reg) {
|
||||
case PMBUS_VIRT_READ_IIN_MAX:
|
||||
ret = pmbus_read_word_data(client, page, LTC3883_MFR_IIN_PEAK);
|
||||
if (ret >= 0) {
|
||||
if (lin11_to_val(ret)
|
||||
> lin11_to_val(data->iin_max))
|
||||
data->iin_max = ret;
|
||||
ret = data->iin_max;
|
||||
}
|
||||
ret = ltc_get_max(data, client, page, LTC3883_MFR_IIN_PEAK,
|
||||
&data->iin_max);
|
||||
break;
|
||||
case PMBUS_VIRT_RESET_IIN_HISTORY:
|
||||
ret = 0;
|
||||
@@ -308,15 +433,15 @@ static int ltc3883_read_word_data(struct i2c_client *client, int page, int reg)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ltc2978_clear_peaks(struct i2c_client *client, int page,
|
||||
enum chips id)
|
||||
static int ltc2978_clear_peaks(struct ltc2978_data *data,
|
||||
struct i2c_client *client, int page)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (id == ltc3880 || id == ltc3883)
|
||||
ret = pmbus_write_byte(client, 0, LTC3880_MFR_CLEAR_PEAKS);
|
||||
if (has_clear_peaks(data))
|
||||
ret = ltc_write_byte(client, 0, LTC3880_MFR_CLEAR_PEAKS);
|
||||
else
|
||||
ret = pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS);
|
||||
ret = ltc_write_byte(client, page, PMBUS_CLEAR_FAULTS);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -331,33 +456,42 @@ static int ltc2978_write_word_data(struct i2c_client *client, int page,
|
||||
switch (reg) {
|
||||
case PMBUS_VIRT_RESET_IIN_HISTORY:
|
||||
data->iin_max = 0x7c00;
|
||||
ret = ltc2978_clear_peaks(client, page, data->id);
|
||||
data->iin_min = 0x7bff;
|
||||
ret = ltc2978_clear_peaks(data, client, 0);
|
||||
break;
|
||||
case PMBUS_VIRT_RESET_PIN_HISTORY:
|
||||
data->pin_max = 0x7c00;
|
||||
data->pin_min = 0x7bff;
|
||||
ret = ltc2978_clear_peaks(data, client, 0);
|
||||
break;
|
||||
case PMBUS_VIRT_RESET_IOUT_HISTORY:
|
||||
data->iout_max[page] = 0x7c00;
|
||||
data->iout_min[page] = 0xfbff;
|
||||
ret = ltc2978_clear_peaks(client, page, data->id);
|
||||
ret = ltc2978_clear_peaks(data, client, page);
|
||||
break;
|
||||
case PMBUS_VIRT_RESET_TEMP2_HISTORY:
|
||||
data->temp2_max = 0x7c00;
|
||||
ret = ltc2978_clear_peaks(client, page, data->id);
|
||||
ret = ltc2978_clear_peaks(data, client, page);
|
||||
break;
|
||||
case PMBUS_VIRT_RESET_VOUT_HISTORY:
|
||||
data->vout_min[page] = 0xffff;
|
||||
data->vout_max[page] = 0;
|
||||
ret = ltc2978_clear_peaks(client, page, data->id);
|
||||
ret = ltc2978_clear_peaks(data, client, page);
|
||||
break;
|
||||
case PMBUS_VIRT_RESET_VIN_HISTORY:
|
||||
data->vin_min = 0x7bff;
|
||||
data->vin_max = 0x7c00;
|
||||
ret = ltc2978_clear_peaks(client, page, data->id);
|
||||
ret = ltc2978_clear_peaks(data, client, page);
|
||||
break;
|
||||
case PMBUS_VIRT_RESET_TEMP_HISTORY:
|
||||
data->temp_min[page] = 0x7bff;
|
||||
data->temp_max[page] = 0x7c00;
|
||||
ret = ltc2978_clear_peaks(client, page, data->id);
|
||||
ret = ltc2978_clear_peaks(data, client, page);
|
||||
break;
|
||||
default:
|
||||
ret = ltc_wait_ready(client);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = -ENODATA;
|
||||
break;
|
||||
}
|
||||
@@ -366,10 +500,17 @@ static int ltc2978_write_word_data(struct i2c_client *client, int page,
|
||||
|
||||
static const struct i2c_device_id ltc2978_id[] = {
|
||||
{"ltc2974", ltc2974},
|
||||
{"ltc2975", ltc2975},
|
||||
{"ltc2977", ltc2977},
|
||||
{"ltc2978", ltc2978},
|
||||
{"ltc2980", ltc2980},
|
||||
{"ltc3880", ltc3880},
|
||||
{"ltc3882", ltc3882},
|
||||
{"ltc3883", ltc3883},
|
||||
{"ltc3886", ltc3886},
|
||||
{"ltc3887", ltc3887},
|
||||
{"ltm2987", ltm2987},
|
||||
{"ltm4675", ltm4675},
|
||||
{"ltm4676", ltm4676},
|
||||
{}
|
||||
};
|
||||
@@ -388,10 +529,74 @@ static const struct regulator_desc ltc2978_reg_desc[] = {
|
||||
};
|
||||
#endif /* CONFIG_SENSORS_LTC2978_REGULATOR */
|
||||
|
||||
static int ltc2978_get_id(struct i2c_client *client)
|
||||
{
|
||||
int chip_id;
|
||||
|
||||
chip_id = i2c_smbus_read_word_data(client, LTC2978_MFR_SPECIAL_ID);
|
||||
if (chip_id < 0) {
|
||||
const struct i2c_device_id *id;
|
||||
u8 buf[I2C_SMBUS_BLOCK_MAX];
|
||||
int ret;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_SMBUS_READ_BLOCK_DATA))
|
||||
return -ENODEV;
|
||||
|
||||
ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, buf);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret < 3 || strncmp(buf, "LTC", 3))
|
||||
return -ENODEV;
|
||||
|
||||
ret = i2c_smbus_read_block_data(client, PMBUS_MFR_MODEL, buf);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
for (id = <c2978_id[0]; strlen(id->name); id++) {
|
||||
if (!strncasecmp(id->name, buf, strlen(id->name)))
|
||||
return (int)id->driver_data;
|
||||
}
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
chip_id &= LTC2978_ID_MASK;
|
||||
|
||||
if (chip_id == LTC2974_ID)
|
||||
return ltc2974;
|
||||
else if (chip_id == LTC2975_ID)
|
||||
return ltc2975;
|
||||
else if (chip_id == LTC2977_ID)
|
||||
return ltc2977;
|
||||
else if (chip_id == LTC2978_ID_REV1 || chip_id == LTC2978_ID_REV2)
|
||||
return ltc2978;
|
||||
else if (chip_id == LTC2980_ID_A || chip_id == LTC2980_ID_B)
|
||||
return ltc2980;
|
||||
else if (chip_id == LTC3880_ID)
|
||||
return ltc3880;
|
||||
else if (chip_id == LTC3882_ID || chip_id == LTC3882_ID_D1)
|
||||
return ltc3882;
|
||||
else if (chip_id == LTC3883_ID)
|
||||
return ltc3883;
|
||||
else if (chip_id == LTC3886_ID)
|
||||
return ltc3886;
|
||||
else if (chip_id == LTC3887_ID)
|
||||
return ltc3887;
|
||||
else if (chip_id == LTM2987_ID_A || chip_id == LTM2987_ID_B)
|
||||
return ltm2987;
|
||||
else if (chip_id == LTM4675_ID)
|
||||
return ltm4675;
|
||||
else if (chip_id == LTM4676_ID_REV1 || chip_id == LTM4676_ID_REV2 ||
|
||||
chip_id == LTM4676A_ID)
|
||||
return ltm4676;
|
||||
|
||||
dev_err(&client->dev, "Unsupported chip ID 0x%x\n", chip_id);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int ltc2978_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
int chip_id, i;
|
||||
int i, chip_id;
|
||||
struct ltc2978_data *data;
|
||||
struct pmbus_driver_info *info;
|
||||
|
||||
@@ -404,27 +609,11 @@ static int ltc2978_probe(struct i2c_client *client,
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
chip_id = i2c_smbus_read_word_data(client, LTC2978_MFR_SPECIAL_ID);
|
||||
chip_id = ltc2978_get_id(client);
|
||||
if (chip_id < 0)
|
||||
return chip_id;
|
||||
|
||||
if (chip_id == LTC2974_ID_REV1 || chip_id == LTC2974_ID_REV2) {
|
||||
data->id = ltc2974;
|
||||
} else if (chip_id == LTC2977_ID) {
|
||||
data->id = ltc2977;
|
||||
} else if (chip_id == LTC2978_ID_REV1 || chip_id == LTC2978_ID_REV2 ||
|
||||
chip_id == LTC2978A_ID) {
|
||||
data->id = ltc2978;
|
||||
} else if ((chip_id & LTC3880_ID_MASK) == LTC3880_ID) {
|
||||
data->id = ltc3880;
|
||||
} else if ((chip_id & LTC3883_ID_MASK) == LTC3883_ID) {
|
||||
data->id = ltc3883;
|
||||
} else if ((chip_id & LTM4676_ID_MASK) == LTM4676_ID) {
|
||||
data->id = ltm4676;
|
||||
} else {
|
||||
dev_err(&client->dev, "Unsupported chip ID 0x%x\n", chip_id);
|
||||
return -ENODEV;
|
||||
}
|
||||
data->id = chip_id;
|
||||
if (data->id != id->driver_data)
|
||||
dev_warn(&client->dev,
|
||||
"Device mismatch: Configured %s, detected %s\n",
|
||||
@@ -433,6 +622,9 @@ static int ltc2978_probe(struct i2c_client *client,
|
||||
|
||||
info = &data->info;
|
||||
info->write_word_data = ltc2978_write_word_data;
|
||||
info->write_byte = ltc_write_byte;
|
||||
info->read_word_data = ltc_read_word_data;
|
||||
info->read_byte_data = ltc_read_byte_data;
|
||||
|
||||
data->vin_min = 0x7bff;
|
||||
data->vin_max = 0x7c00;
|
||||
@@ -461,8 +653,23 @@ static int ltc2978_probe(struct i2c_client *client,
|
||||
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
|
||||
}
|
||||
break;
|
||||
case ltc2975:
|
||||
info->read_word_data = ltc2975_read_word_data;
|
||||
info->pages = LTC2974_NUM_PAGES;
|
||||
info->func[0] = PMBUS_HAVE_IIN | PMBUS_HAVE_PIN
|
||||
| PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
|
||||
| PMBUS_HAVE_TEMP2;
|
||||
for (i = 0; i < info->pages; i++) {
|
||||
info->func[i] |= PMBUS_HAVE_VOUT
|
||||
| PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_POUT
|
||||
| PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP
|
||||
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
|
||||
}
|
||||
break;
|
||||
case ltc2977:
|
||||
case ltc2978:
|
||||
case ltc2980:
|
||||
case ltm2987:
|
||||
info->read_word_data = ltc2978_read_word_data;
|
||||
info->pages = LTC2978_NUM_PAGES;
|
||||
info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
|
||||
@@ -474,7 +681,10 @@ static int ltc2978_probe(struct i2c_client *client,
|
||||
}
|
||||
break;
|
||||
case ltc3880:
|
||||
case ltc3887:
|
||||
case ltm4675:
|
||||
case ltm4676:
|
||||
data->features |= FEAT_CLEAR_PEAKS | FEAT_NEEDS_POLLING;
|
||||
info->read_word_data = ltc3880_read_word_data;
|
||||
info->pages = LTC3880_NUM_PAGES;
|
||||
info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN
|
||||
@@ -488,7 +698,23 @@ static int ltc2978_probe(struct i2c_client *client,
|
||||
| PMBUS_HAVE_POUT
|
||||
| PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
|
||||
break;
|
||||
case ltc3882:
|
||||
data->features |= FEAT_CLEAR_PEAKS | FEAT_NEEDS_POLLING;
|
||||
info->read_word_data = ltc3880_read_word_data;
|
||||
info->pages = LTC3880_NUM_PAGES;
|
||||
info->func[0] = PMBUS_HAVE_VIN
|
||||
| PMBUS_HAVE_STATUS_INPUT
|
||||
| PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
|
||||
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
|
||||
| PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
|
||||
| PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;
|
||||
info->func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
|
||||
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
|
||||
| PMBUS_HAVE_POUT
|
||||
| PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
|
||||
break;
|
||||
case ltc3883:
|
||||
data->features |= FEAT_CLEAR_PEAKS | FEAT_NEEDS_POLLING;
|
||||
info->read_word_data = ltc3883_read_word_data;
|
||||
info->pages = LTC3883_NUM_PAGES;
|
||||
info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN
|
||||
@@ -498,6 +724,21 @@ static int ltc2978_probe(struct i2c_client *client,
|
||||
| PMBUS_HAVE_PIN | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
|
||||
| PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;
|
||||
break;
|
||||
case ltc3886:
|
||||
data->features |= FEAT_CLEAR_PEAKS | FEAT_NEEDS_POLLING;
|
||||
info->read_word_data = ltc3883_read_word_data;
|
||||
info->pages = LTC3880_NUM_PAGES;
|
||||
info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN
|
||||
| PMBUS_HAVE_STATUS_INPUT
|
||||
| PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
|
||||
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
|
||||
| PMBUS_HAVE_PIN | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
|
||||
| PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;
|
||||
info->func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
|
||||
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
|
||||
| PMBUS_HAVE_POUT
|
||||
| PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
|
||||
break;
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
@@ -517,10 +758,17 @@ static int ltc2978_probe(struct i2c_client *client,
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id ltc2978_of_match[] = {
|
||||
{ .compatible = "lltc,ltc2974" },
|
||||
{ .compatible = "lltc,ltc2975" },
|
||||
{ .compatible = "lltc,ltc2977" },
|
||||
{ .compatible = "lltc,ltc2978" },
|
||||
{ .compatible = "lltc,ltc2980" },
|
||||
{ .compatible = "lltc,ltc3880" },
|
||||
{ .compatible = "lltc,ltc3882" },
|
||||
{ .compatible = "lltc,ltc3883" },
|
||||
{ .compatible = "lltc,ltc3886" },
|
||||
{ .compatible = "lltc,ltc3887" },
|
||||
{ .compatible = "lltc,ltm2987" },
|
||||
{ .compatible = "lltc,ltm4675" },
|
||||
{ .compatible = "lltc,ltm4676" },
|
||||
{ }
|
||||
};
|
||||
@@ -540,5 +788,5 @@ static struct i2c_driver ltc2978_driver = {
|
||||
module_i2c_driver(ltc2978_driver);
|
||||
|
||||
MODULE_AUTHOR("Guenter Roeck");
|
||||
MODULE_DESCRIPTION("PMBus driver for LTC2974, LTC2978, LTC3880, LTC3883, and LTM4676");
|
||||
MODULE_DESCRIPTION("PMBus driver for LTC2978 and comppatible chips");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Hardware monitoring driver for Maxim MAX20751
|
||||
*
|
||||
* Copyright (c) 2015 Guenter Roeck
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/i2c.h>
|
||||
#include "pmbus.h"
|
||||
|
||||
static struct pmbus_driver_info max20751_info = {
|
||||
.pages = 1,
|
||||
.format[PSC_VOLTAGE_IN] = linear,
|
||||
.format[PSC_VOLTAGE_OUT] = vid,
|
||||
.vrm_version = vr12,
|
||||
.format[PSC_TEMPERATURE] = linear,
|
||||
.format[PSC_CURRENT_OUT] = linear,
|
||||
.format[PSC_POWER] = linear,
|
||||
.func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
|
||||
PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
|
||||
PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP |
|
||||
PMBUS_HAVE_POUT,
|
||||
};
|
||||
|
||||
static int max20751_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
return pmbus_do_probe(client, id, &max20751_info);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id max20751_id[] = {
|
||||
{"max20751", 0},
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, max20751_id);
|
||||
|
||||
static struct i2c_driver max20751_driver = {
|
||||
.driver = {
|
||||
.name = "max20751",
|
||||
},
|
||||
.probe = max20751_probe,
|
||||
.remove = pmbus_do_remove,
|
||||
.id_table = max20751_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(max20751_driver);
|
||||
|
||||
MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
|
||||
MODULE_DESCRIPTION("PMBus driver for Maxim MAX20751");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -19,6 +19,7 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
@@ -38,10 +39,10 @@ enum chips { max34440, max34441, max34446, max34460, max34461 };
|
||||
#define MAX34446_MFR_IOUT_AVG 0xe2
|
||||
#define MAX34446_MFR_TEMPERATURE_AVG 0xe3
|
||||
|
||||
#define MAX34440_STATUS_OC_WARN (1 << 0)
|
||||
#define MAX34440_STATUS_OC_FAULT (1 << 1)
|
||||
#define MAX34440_STATUS_OT_FAULT (1 << 5)
|
||||
#define MAX34440_STATUS_OT_WARN (1 << 6)
|
||||
#define MAX34440_STATUS_OC_WARN BIT(0)
|
||||
#define MAX34440_STATUS_OC_FAULT BIT(1)
|
||||
#define MAX34440_STATUS_OT_FAULT BIT(5)
|
||||
#define MAX34440_STATUS_OT_WARN BIT(6)
|
||||
|
||||
struct max34440_data {
|
||||
int id;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
@@ -30,15 +31,15 @@
|
||||
#define MAX8688_MFR_TEMPERATURE_PEAK 0xd6
|
||||
#define MAX8688_MFG_STATUS 0xd8
|
||||
|
||||
#define MAX8688_STATUS_OC_FAULT (1 << 4)
|
||||
#define MAX8688_STATUS_OV_FAULT (1 << 5)
|
||||
#define MAX8688_STATUS_OV_WARNING (1 << 8)
|
||||
#define MAX8688_STATUS_UV_FAULT (1 << 9)
|
||||
#define MAX8688_STATUS_UV_WARNING (1 << 10)
|
||||
#define MAX8688_STATUS_UC_FAULT (1 << 11)
|
||||
#define MAX8688_STATUS_OC_WARNING (1 << 12)
|
||||
#define MAX8688_STATUS_OT_FAULT (1 << 13)
|
||||
#define MAX8688_STATUS_OT_WARNING (1 << 14)
|
||||
#define MAX8688_STATUS_OC_FAULT BIT(4)
|
||||
#define MAX8688_STATUS_OV_FAULT BIT(5)
|
||||
#define MAX8688_STATUS_OV_WARNING BIT(8)
|
||||
#define MAX8688_STATUS_UV_FAULT BIT(9)
|
||||
#define MAX8688_STATUS_UV_WARNING BIT(10)
|
||||
#define MAX8688_STATUS_UC_FAULT BIT(11)
|
||||
#define MAX8688_STATUS_OC_WARNING BIT(12)
|
||||
#define MAX8688_STATUS_OT_FAULT BIT(13)
|
||||
#define MAX8688_STATUS_OT_WARNING BIT(14)
|
||||
|
||||
static int max8688_read_word_data(struct i2c_client *client, int page, int reg)
|
||||
{
|
||||
|
||||
@@ -129,6 +129,7 @@ static int pmbus_identify(struct i2c_client *client,
|
||||
break;
|
||||
case 1:
|
||||
info->format[PSC_VOLTAGE_OUT] = vid;
|
||||
info->vrm_version = vr11;
|
||||
break;
|
||||
case 2:
|
||||
info->format[PSC_VOLTAGE_OUT] = direct;
|
||||
@@ -193,6 +194,10 @@ static const struct i2c_device_id pmbus_id[] = {
|
||||
{"pdt012", 1},
|
||||
{"pmbus", 0},
|
||||
{"tps40400", 1},
|
||||
{"tps544b20", 1},
|
||||
{"tps544b25", 1},
|
||||
{"tps544c20", 1},
|
||||
{"tps544c25", 1},
|
||||
{"udt020", 1},
|
||||
{}
|
||||
};
|
||||
|
||||
+216
-208
@@ -19,114 +19,116 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/regulator/driver.h>
|
||||
|
||||
#ifndef PMBUS_H
|
||||
#define PMBUS_H
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
|
||||
/*
|
||||
* Registers
|
||||
*/
|
||||
#define PMBUS_PAGE 0x00
|
||||
#define PMBUS_OPERATION 0x01
|
||||
#define PMBUS_ON_OFF_CONFIG 0x02
|
||||
#define PMBUS_CLEAR_FAULTS 0x03
|
||||
#define PMBUS_PHASE 0x04
|
||||
enum pmbus_regs {
|
||||
PMBUS_PAGE = 0x00,
|
||||
PMBUS_OPERATION = 0x01,
|
||||
PMBUS_ON_OFF_CONFIG = 0x02,
|
||||
PMBUS_CLEAR_FAULTS = 0x03,
|
||||
PMBUS_PHASE = 0x04,
|
||||
|
||||
#define PMBUS_CAPABILITY 0x19
|
||||
#define PMBUS_QUERY 0x1A
|
||||
PMBUS_CAPABILITY = 0x19,
|
||||
PMBUS_QUERY = 0x1A,
|
||||
|
||||
#define PMBUS_VOUT_MODE 0x20
|
||||
#define PMBUS_VOUT_COMMAND 0x21
|
||||
#define PMBUS_VOUT_TRIM 0x22
|
||||
#define PMBUS_VOUT_CAL_OFFSET 0x23
|
||||
#define PMBUS_VOUT_MAX 0x24
|
||||
#define PMBUS_VOUT_MARGIN_HIGH 0x25
|
||||
#define PMBUS_VOUT_MARGIN_LOW 0x26
|
||||
#define PMBUS_VOUT_TRANSITION_RATE 0x27
|
||||
#define PMBUS_VOUT_DROOP 0x28
|
||||
#define PMBUS_VOUT_SCALE_LOOP 0x29
|
||||
#define PMBUS_VOUT_SCALE_MONITOR 0x2A
|
||||
PMBUS_VOUT_MODE = 0x20,
|
||||
PMBUS_VOUT_COMMAND = 0x21,
|
||||
PMBUS_VOUT_TRIM = 0x22,
|
||||
PMBUS_VOUT_CAL_OFFSET = 0x23,
|
||||
PMBUS_VOUT_MAX = 0x24,
|
||||
PMBUS_VOUT_MARGIN_HIGH = 0x25,
|
||||
PMBUS_VOUT_MARGIN_LOW = 0x26,
|
||||
PMBUS_VOUT_TRANSITION_RATE = 0x27,
|
||||
PMBUS_VOUT_DROOP = 0x28,
|
||||
PMBUS_VOUT_SCALE_LOOP = 0x29,
|
||||
PMBUS_VOUT_SCALE_MONITOR = 0x2A,
|
||||
|
||||
#define PMBUS_COEFFICIENTS 0x30
|
||||
#define PMBUS_POUT_MAX 0x31
|
||||
PMBUS_COEFFICIENTS = 0x30,
|
||||
PMBUS_POUT_MAX = 0x31,
|
||||
|
||||
#define PMBUS_FAN_CONFIG_12 0x3A
|
||||
#define PMBUS_FAN_COMMAND_1 0x3B
|
||||
#define PMBUS_FAN_COMMAND_2 0x3C
|
||||
#define PMBUS_FAN_CONFIG_34 0x3D
|
||||
#define PMBUS_FAN_COMMAND_3 0x3E
|
||||
#define PMBUS_FAN_COMMAND_4 0x3F
|
||||
PMBUS_FAN_CONFIG_12 = 0x3A,
|
||||
PMBUS_FAN_COMMAND_1 = 0x3B,
|
||||
PMBUS_FAN_COMMAND_2 = 0x3C,
|
||||
PMBUS_FAN_CONFIG_34 = 0x3D,
|
||||
PMBUS_FAN_COMMAND_3 = 0x3E,
|
||||
PMBUS_FAN_COMMAND_4 = 0x3F,
|
||||
|
||||
#define PMBUS_VOUT_OV_FAULT_LIMIT 0x40
|
||||
#define PMBUS_VOUT_OV_FAULT_RESPONSE 0x41
|
||||
#define PMBUS_VOUT_OV_WARN_LIMIT 0x42
|
||||
#define PMBUS_VOUT_UV_WARN_LIMIT 0x43
|
||||
#define PMBUS_VOUT_UV_FAULT_LIMIT 0x44
|
||||
#define PMBUS_VOUT_UV_FAULT_RESPONSE 0x45
|
||||
#define PMBUS_IOUT_OC_FAULT_LIMIT 0x46
|
||||
#define PMBUS_IOUT_OC_FAULT_RESPONSE 0x47
|
||||
#define PMBUS_IOUT_OC_LV_FAULT_LIMIT 0x48
|
||||
#define PMBUS_IOUT_OC_LV_FAULT_RESPONSE 0x49
|
||||
#define PMBUS_IOUT_OC_WARN_LIMIT 0x4A
|
||||
#define PMBUS_IOUT_UC_FAULT_LIMIT 0x4B
|
||||
#define PMBUS_IOUT_UC_FAULT_RESPONSE 0x4C
|
||||
PMBUS_VOUT_OV_FAULT_LIMIT = 0x40,
|
||||
PMBUS_VOUT_OV_FAULT_RESPONSE = 0x41,
|
||||
PMBUS_VOUT_OV_WARN_LIMIT = 0x42,
|
||||
PMBUS_VOUT_UV_WARN_LIMIT = 0x43,
|
||||
PMBUS_VOUT_UV_FAULT_LIMIT = 0x44,
|
||||
PMBUS_VOUT_UV_FAULT_RESPONSE = 0x45,
|
||||
PMBUS_IOUT_OC_FAULT_LIMIT = 0x46,
|
||||
PMBUS_IOUT_OC_FAULT_RESPONSE = 0x47,
|
||||
PMBUS_IOUT_OC_LV_FAULT_LIMIT = 0x48,
|
||||
PMBUS_IOUT_OC_LV_FAULT_RESPONSE = 0x49,
|
||||
PMBUS_IOUT_OC_WARN_LIMIT = 0x4A,
|
||||
PMBUS_IOUT_UC_FAULT_LIMIT = 0x4B,
|
||||
PMBUS_IOUT_UC_FAULT_RESPONSE = 0x4C,
|
||||
|
||||
#define PMBUS_OT_FAULT_LIMIT 0x4F
|
||||
#define PMBUS_OT_FAULT_RESPONSE 0x50
|
||||
#define PMBUS_OT_WARN_LIMIT 0x51
|
||||
#define PMBUS_UT_WARN_LIMIT 0x52
|
||||
#define PMBUS_UT_FAULT_LIMIT 0x53
|
||||
#define PMBUS_UT_FAULT_RESPONSE 0x54
|
||||
#define PMBUS_VIN_OV_FAULT_LIMIT 0x55
|
||||
#define PMBUS_VIN_OV_FAULT_RESPONSE 0x56
|
||||
#define PMBUS_VIN_OV_WARN_LIMIT 0x57
|
||||
#define PMBUS_VIN_UV_WARN_LIMIT 0x58
|
||||
#define PMBUS_VIN_UV_FAULT_LIMIT 0x59
|
||||
PMBUS_OT_FAULT_LIMIT = 0x4F,
|
||||
PMBUS_OT_FAULT_RESPONSE = 0x50,
|
||||
PMBUS_OT_WARN_LIMIT = 0x51,
|
||||
PMBUS_UT_WARN_LIMIT = 0x52,
|
||||
PMBUS_UT_FAULT_LIMIT = 0x53,
|
||||
PMBUS_UT_FAULT_RESPONSE = 0x54,
|
||||
PMBUS_VIN_OV_FAULT_LIMIT = 0x55,
|
||||
PMBUS_VIN_OV_FAULT_RESPONSE = 0x56,
|
||||
PMBUS_VIN_OV_WARN_LIMIT = 0x57,
|
||||
PMBUS_VIN_UV_WARN_LIMIT = 0x58,
|
||||
PMBUS_VIN_UV_FAULT_LIMIT = 0x59,
|
||||
|
||||
#define PMBUS_IIN_OC_FAULT_LIMIT 0x5B
|
||||
#define PMBUS_IIN_OC_WARN_LIMIT 0x5D
|
||||
PMBUS_IIN_OC_FAULT_LIMIT = 0x5B,
|
||||
PMBUS_IIN_OC_WARN_LIMIT = 0x5D,
|
||||
|
||||
#define PMBUS_POUT_OP_FAULT_LIMIT 0x68
|
||||
#define PMBUS_POUT_OP_WARN_LIMIT 0x6A
|
||||
#define PMBUS_PIN_OP_WARN_LIMIT 0x6B
|
||||
PMBUS_POUT_OP_FAULT_LIMIT = 0x68,
|
||||
PMBUS_POUT_OP_WARN_LIMIT = 0x6A,
|
||||
PMBUS_PIN_OP_WARN_LIMIT = 0x6B,
|
||||
|
||||
#define PMBUS_STATUS_BYTE 0x78
|
||||
#define PMBUS_STATUS_WORD 0x79
|
||||
#define PMBUS_STATUS_VOUT 0x7A
|
||||
#define PMBUS_STATUS_IOUT 0x7B
|
||||
#define PMBUS_STATUS_INPUT 0x7C
|
||||
#define PMBUS_STATUS_TEMPERATURE 0x7D
|
||||
#define PMBUS_STATUS_CML 0x7E
|
||||
#define PMBUS_STATUS_OTHER 0x7F
|
||||
#define PMBUS_STATUS_MFR_SPECIFIC 0x80
|
||||
#define PMBUS_STATUS_FAN_12 0x81
|
||||
#define PMBUS_STATUS_FAN_34 0x82
|
||||
PMBUS_STATUS_BYTE = 0x78,
|
||||
PMBUS_STATUS_WORD = 0x79,
|
||||
PMBUS_STATUS_VOUT = 0x7A,
|
||||
PMBUS_STATUS_IOUT = 0x7B,
|
||||
PMBUS_STATUS_INPUT = 0x7C,
|
||||
PMBUS_STATUS_TEMPERATURE = 0x7D,
|
||||
PMBUS_STATUS_CML = 0x7E,
|
||||
PMBUS_STATUS_OTHER = 0x7F,
|
||||
PMBUS_STATUS_MFR_SPECIFIC = 0x80,
|
||||
PMBUS_STATUS_FAN_12 = 0x81,
|
||||
PMBUS_STATUS_FAN_34 = 0x82,
|
||||
|
||||
#define PMBUS_READ_VIN 0x88
|
||||
#define PMBUS_READ_IIN 0x89
|
||||
#define PMBUS_READ_VCAP 0x8A
|
||||
#define PMBUS_READ_VOUT 0x8B
|
||||
#define PMBUS_READ_IOUT 0x8C
|
||||
#define PMBUS_READ_TEMPERATURE_1 0x8D
|
||||
#define PMBUS_READ_TEMPERATURE_2 0x8E
|
||||
#define PMBUS_READ_TEMPERATURE_3 0x8F
|
||||
#define PMBUS_READ_FAN_SPEED_1 0x90
|
||||
#define PMBUS_READ_FAN_SPEED_2 0x91
|
||||
#define PMBUS_READ_FAN_SPEED_3 0x92
|
||||
#define PMBUS_READ_FAN_SPEED_4 0x93
|
||||
#define PMBUS_READ_DUTY_CYCLE 0x94
|
||||
#define PMBUS_READ_FREQUENCY 0x95
|
||||
#define PMBUS_READ_POUT 0x96
|
||||
#define PMBUS_READ_PIN 0x97
|
||||
PMBUS_READ_VIN = 0x88,
|
||||
PMBUS_READ_IIN = 0x89,
|
||||
PMBUS_READ_VCAP = 0x8A,
|
||||
PMBUS_READ_VOUT = 0x8B,
|
||||
PMBUS_READ_IOUT = 0x8C,
|
||||
PMBUS_READ_TEMPERATURE_1 = 0x8D,
|
||||
PMBUS_READ_TEMPERATURE_2 = 0x8E,
|
||||
PMBUS_READ_TEMPERATURE_3 = 0x8F,
|
||||
PMBUS_READ_FAN_SPEED_1 = 0x90,
|
||||
PMBUS_READ_FAN_SPEED_2 = 0x91,
|
||||
PMBUS_READ_FAN_SPEED_3 = 0x92,
|
||||
PMBUS_READ_FAN_SPEED_4 = 0x93,
|
||||
PMBUS_READ_DUTY_CYCLE = 0x94,
|
||||
PMBUS_READ_FREQUENCY = 0x95,
|
||||
PMBUS_READ_POUT = 0x96,
|
||||
PMBUS_READ_PIN = 0x97,
|
||||
|
||||
#define PMBUS_REVISION 0x98
|
||||
#define PMBUS_MFR_ID 0x99
|
||||
#define PMBUS_MFR_MODEL 0x9A
|
||||
#define PMBUS_MFR_REVISION 0x9B
|
||||
#define PMBUS_MFR_LOCATION 0x9C
|
||||
#define PMBUS_MFR_DATE 0x9D
|
||||
#define PMBUS_MFR_SERIAL 0x9E
|
||||
PMBUS_REVISION = 0x98,
|
||||
PMBUS_MFR_ID = 0x99,
|
||||
PMBUS_MFR_MODEL = 0x9A,
|
||||
PMBUS_MFR_REVISION = 0x9B,
|
||||
PMBUS_MFR_LOCATION = 0x9C,
|
||||
PMBUS_MFR_DATE = 0x9D,
|
||||
PMBUS_MFR_SERIAL = 0x9E,
|
||||
|
||||
/*
|
||||
* Virtual registers.
|
||||
@@ -148,55 +150,58 @@
|
||||
* the calling PMBus core code will abort if the chip driver returns an error
|
||||
* code when reading or writing virtual registers.
|
||||
*/
|
||||
#define PMBUS_VIRT_BASE 0x100
|
||||
#define PMBUS_VIRT_READ_TEMP_AVG (PMBUS_VIRT_BASE + 0)
|
||||
#define PMBUS_VIRT_READ_TEMP_MIN (PMBUS_VIRT_BASE + 1)
|
||||
#define PMBUS_VIRT_READ_TEMP_MAX (PMBUS_VIRT_BASE + 2)
|
||||
#define PMBUS_VIRT_RESET_TEMP_HISTORY (PMBUS_VIRT_BASE + 3)
|
||||
#define PMBUS_VIRT_READ_VIN_AVG (PMBUS_VIRT_BASE + 4)
|
||||
#define PMBUS_VIRT_READ_VIN_MIN (PMBUS_VIRT_BASE + 5)
|
||||
#define PMBUS_VIRT_READ_VIN_MAX (PMBUS_VIRT_BASE + 6)
|
||||
#define PMBUS_VIRT_RESET_VIN_HISTORY (PMBUS_VIRT_BASE + 7)
|
||||
#define PMBUS_VIRT_READ_IIN_AVG (PMBUS_VIRT_BASE + 8)
|
||||
#define PMBUS_VIRT_READ_IIN_MIN (PMBUS_VIRT_BASE + 9)
|
||||
#define PMBUS_VIRT_READ_IIN_MAX (PMBUS_VIRT_BASE + 10)
|
||||
#define PMBUS_VIRT_RESET_IIN_HISTORY (PMBUS_VIRT_BASE + 11)
|
||||
#define PMBUS_VIRT_READ_PIN_AVG (PMBUS_VIRT_BASE + 12)
|
||||
#define PMBUS_VIRT_READ_PIN_MAX (PMBUS_VIRT_BASE + 13)
|
||||
#define PMBUS_VIRT_RESET_PIN_HISTORY (PMBUS_VIRT_BASE + 14)
|
||||
#define PMBUS_VIRT_READ_POUT_AVG (PMBUS_VIRT_BASE + 15)
|
||||
#define PMBUS_VIRT_READ_POUT_MAX (PMBUS_VIRT_BASE + 16)
|
||||
#define PMBUS_VIRT_RESET_POUT_HISTORY (PMBUS_VIRT_BASE + 17)
|
||||
#define PMBUS_VIRT_READ_VOUT_AVG (PMBUS_VIRT_BASE + 18)
|
||||
#define PMBUS_VIRT_READ_VOUT_MIN (PMBUS_VIRT_BASE + 19)
|
||||
#define PMBUS_VIRT_READ_VOUT_MAX (PMBUS_VIRT_BASE + 20)
|
||||
#define PMBUS_VIRT_RESET_VOUT_HISTORY (PMBUS_VIRT_BASE + 21)
|
||||
#define PMBUS_VIRT_READ_IOUT_AVG (PMBUS_VIRT_BASE + 22)
|
||||
#define PMBUS_VIRT_READ_IOUT_MIN (PMBUS_VIRT_BASE + 23)
|
||||
#define PMBUS_VIRT_READ_IOUT_MAX (PMBUS_VIRT_BASE + 24)
|
||||
#define PMBUS_VIRT_RESET_IOUT_HISTORY (PMBUS_VIRT_BASE + 25)
|
||||
#define PMBUS_VIRT_READ_TEMP2_AVG (PMBUS_VIRT_BASE + 26)
|
||||
#define PMBUS_VIRT_READ_TEMP2_MIN (PMBUS_VIRT_BASE + 27)
|
||||
#define PMBUS_VIRT_READ_TEMP2_MAX (PMBUS_VIRT_BASE + 28)
|
||||
#define PMBUS_VIRT_RESET_TEMP2_HISTORY (PMBUS_VIRT_BASE + 29)
|
||||
PMBUS_VIRT_BASE = 0x100,
|
||||
PMBUS_VIRT_READ_TEMP_AVG,
|
||||
PMBUS_VIRT_READ_TEMP_MIN,
|
||||
PMBUS_VIRT_READ_TEMP_MAX,
|
||||
PMBUS_VIRT_RESET_TEMP_HISTORY,
|
||||
PMBUS_VIRT_READ_VIN_AVG,
|
||||
PMBUS_VIRT_READ_VIN_MIN,
|
||||
PMBUS_VIRT_READ_VIN_MAX,
|
||||
PMBUS_VIRT_RESET_VIN_HISTORY,
|
||||
PMBUS_VIRT_READ_IIN_AVG,
|
||||
PMBUS_VIRT_READ_IIN_MIN,
|
||||
PMBUS_VIRT_READ_IIN_MAX,
|
||||
PMBUS_VIRT_RESET_IIN_HISTORY,
|
||||
PMBUS_VIRT_READ_PIN_AVG,
|
||||
PMBUS_VIRT_READ_PIN_MIN,
|
||||
PMBUS_VIRT_READ_PIN_MAX,
|
||||
PMBUS_VIRT_RESET_PIN_HISTORY,
|
||||
PMBUS_VIRT_READ_POUT_AVG,
|
||||
PMBUS_VIRT_READ_POUT_MIN,
|
||||
PMBUS_VIRT_READ_POUT_MAX,
|
||||
PMBUS_VIRT_RESET_POUT_HISTORY,
|
||||
PMBUS_VIRT_READ_VOUT_AVG,
|
||||
PMBUS_VIRT_READ_VOUT_MIN,
|
||||
PMBUS_VIRT_READ_VOUT_MAX,
|
||||
PMBUS_VIRT_RESET_VOUT_HISTORY,
|
||||
PMBUS_VIRT_READ_IOUT_AVG,
|
||||
PMBUS_VIRT_READ_IOUT_MIN,
|
||||
PMBUS_VIRT_READ_IOUT_MAX,
|
||||
PMBUS_VIRT_RESET_IOUT_HISTORY,
|
||||
PMBUS_VIRT_READ_TEMP2_AVG,
|
||||
PMBUS_VIRT_READ_TEMP2_MIN,
|
||||
PMBUS_VIRT_READ_TEMP2_MAX,
|
||||
PMBUS_VIRT_RESET_TEMP2_HISTORY,
|
||||
|
||||
#define PMBUS_VIRT_READ_VMON (PMBUS_VIRT_BASE + 30)
|
||||
#define PMBUS_VIRT_VMON_UV_WARN_LIMIT (PMBUS_VIRT_BASE + 31)
|
||||
#define PMBUS_VIRT_VMON_OV_WARN_LIMIT (PMBUS_VIRT_BASE + 32)
|
||||
#define PMBUS_VIRT_VMON_UV_FAULT_LIMIT (PMBUS_VIRT_BASE + 33)
|
||||
#define PMBUS_VIRT_VMON_OV_FAULT_LIMIT (PMBUS_VIRT_BASE + 34)
|
||||
#define PMBUS_VIRT_STATUS_VMON (PMBUS_VIRT_BASE + 35)
|
||||
PMBUS_VIRT_READ_VMON,
|
||||
PMBUS_VIRT_VMON_UV_WARN_LIMIT,
|
||||
PMBUS_VIRT_VMON_OV_WARN_LIMIT,
|
||||
PMBUS_VIRT_VMON_UV_FAULT_LIMIT,
|
||||
PMBUS_VIRT_VMON_OV_FAULT_LIMIT,
|
||||
PMBUS_VIRT_STATUS_VMON,
|
||||
};
|
||||
|
||||
/*
|
||||
* OPERATION
|
||||
*/
|
||||
#define PB_OPERATION_CONTROL_ON (1<<7)
|
||||
#define PB_OPERATION_CONTROL_ON BIT(7)
|
||||
|
||||
/*
|
||||
* CAPABILITY
|
||||
*/
|
||||
#define PB_CAPABILITY_SMBALERT (1<<4)
|
||||
#define PB_CAPABILITY_ERROR_CHECK (1<<7)
|
||||
#define PB_CAPABILITY_SMBALERT BIT(4)
|
||||
#define PB_CAPABILITY_ERROR_CHECK BIT(7)
|
||||
|
||||
/*
|
||||
* VOUT_MODE
|
||||
@@ -211,94 +216,94 @@
|
||||
/*
|
||||
* Fan configuration
|
||||
*/
|
||||
#define PB_FAN_2_PULSE_MASK ((1 << 0) | (1 << 1))
|
||||
#define PB_FAN_2_RPM (1 << 2)
|
||||
#define PB_FAN_2_INSTALLED (1 << 3)
|
||||
#define PB_FAN_1_PULSE_MASK ((1 << 4) | (1 << 5))
|
||||
#define PB_FAN_1_RPM (1 << 6)
|
||||
#define PB_FAN_1_INSTALLED (1 << 7)
|
||||
#define PB_FAN_2_PULSE_MASK (BIT(0) | BIT(1))
|
||||
#define PB_FAN_2_RPM BIT(2)
|
||||
#define PB_FAN_2_INSTALLED BIT(3)
|
||||
#define PB_FAN_1_PULSE_MASK (BIT(4) | BIT(5))
|
||||
#define PB_FAN_1_RPM BIT(6)
|
||||
#define PB_FAN_1_INSTALLED BIT(7)
|
||||
|
||||
/*
|
||||
* STATUS_BYTE, STATUS_WORD (lower)
|
||||
*/
|
||||
#define PB_STATUS_NONE_ABOVE (1<<0)
|
||||
#define PB_STATUS_CML (1<<1)
|
||||
#define PB_STATUS_TEMPERATURE (1<<2)
|
||||
#define PB_STATUS_VIN_UV (1<<3)
|
||||
#define PB_STATUS_IOUT_OC (1<<4)
|
||||
#define PB_STATUS_VOUT_OV (1<<5)
|
||||
#define PB_STATUS_OFF (1<<6)
|
||||
#define PB_STATUS_BUSY (1<<7)
|
||||
#define PB_STATUS_NONE_ABOVE BIT(0)
|
||||
#define PB_STATUS_CML BIT(1)
|
||||
#define PB_STATUS_TEMPERATURE BIT(2)
|
||||
#define PB_STATUS_VIN_UV BIT(3)
|
||||
#define PB_STATUS_IOUT_OC BIT(4)
|
||||
#define PB_STATUS_VOUT_OV BIT(5)
|
||||
#define PB_STATUS_OFF BIT(6)
|
||||
#define PB_STATUS_BUSY BIT(7)
|
||||
|
||||
/*
|
||||
* STATUS_WORD (upper)
|
||||
*/
|
||||
#define PB_STATUS_UNKNOWN (1<<8)
|
||||
#define PB_STATUS_OTHER (1<<9)
|
||||
#define PB_STATUS_FANS (1<<10)
|
||||
#define PB_STATUS_POWER_GOOD_N (1<<11)
|
||||
#define PB_STATUS_WORD_MFR (1<<12)
|
||||
#define PB_STATUS_INPUT (1<<13)
|
||||
#define PB_STATUS_IOUT_POUT (1<<14)
|
||||
#define PB_STATUS_VOUT (1<<15)
|
||||
#define PB_STATUS_UNKNOWN BIT(8)
|
||||
#define PB_STATUS_OTHER BIT(9)
|
||||
#define PB_STATUS_FANS BIT(10)
|
||||
#define PB_STATUS_POWER_GOOD_N BIT(11)
|
||||
#define PB_STATUS_WORD_MFR BIT(12)
|
||||
#define PB_STATUS_INPUT BIT(13)
|
||||
#define PB_STATUS_IOUT_POUT BIT(14)
|
||||
#define PB_STATUS_VOUT BIT(15)
|
||||
|
||||
/*
|
||||
* STATUS_IOUT
|
||||
*/
|
||||
#define PB_POUT_OP_WARNING (1<<0)
|
||||
#define PB_POUT_OP_FAULT (1<<1)
|
||||
#define PB_POWER_LIMITING (1<<2)
|
||||
#define PB_CURRENT_SHARE_FAULT (1<<3)
|
||||
#define PB_IOUT_UC_FAULT (1<<4)
|
||||
#define PB_IOUT_OC_WARNING (1<<5)
|
||||
#define PB_IOUT_OC_LV_FAULT (1<<6)
|
||||
#define PB_IOUT_OC_FAULT (1<<7)
|
||||
#define PB_POUT_OP_WARNING BIT(0)
|
||||
#define PB_POUT_OP_FAULT BIT(1)
|
||||
#define PB_POWER_LIMITING BIT(2)
|
||||
#define PB_CURRENT_SHARE_FAULT BIT(3)
|
||||
#define PB_IOUT_UC_FAULT BIT(4)
|
||||
#define PB_IOUT_OC_WARNING BIT(5)
|
||||
#define PB_IOUT_OC_LV_FAULT BIT(6)
|
||||
#define PB_IOUT_OC_FAULT BIT(7)
|
||||
|
||||
/*
|
||||
* STATUS_VOUT, STATUS_INPUT
|
||||
*/
|
||||
#define PB_VOLTAGE_UV_FAULT (1<<4)
|
||||
#define PB_VOLTAGE_UV_WARNING (1<<5)
|
||||
#define PB_VOLTAGE_OV_WARNING (1<<6)
|
||||
#define PB_VOLTAGE_OV_FAULT (1<<7)
|
||||
#define PB_VOLTAGE_UV_FAULT BIT(4)
|
||||
#define PB_VOLTAGE_UV_WARNING BIT(5)
|
||||
#define PB_VOLTAGE_OV_WARNING BIT(6)
|
||||
#define PB_VOLTAGE_OV_FAULT BIT(7)
|
||||
|
||||
/*
|
||||
* STATUS_INPUT
|
||||
*/
|
||||
#define PB_PIN_OP_WARNING (1<<0)
|
||||
#define PB_IIN_OC_WARNING (1<<1)
|
||||
#define PB_IIN_OC_FAULT (1<<2)
|
||||
#define PB_PIN_OP_WARNING BIT(0)
|
||||
#define PB_IIN_OC_WARNING BIT(1)
|
||||
#define PB_IIN_OC_FAULT BIT(2)
|
||||
|
||||
/*
|
||||
* STATUS_TEMPERATURE
|
||||
*/
|
||||
#define PB_TEMP_UT_FAULT (1<<4)
|
||||
#define PB_TEMP_UT_WARNING (1<<5)
|
||||
#define PB_TEMP_OT_WARNING (1<<6)
|
||||
#define PB_TEMP_OT_FAULT (1<<7)
|
||||
#define PB_TEMP_UT_FAULT BIT(4)
|
||||
#define PB_TEMP_UT_WARNING BIT(5)
|
||||
#define PB_TEMP_OT_WARNING BIT(6)
|
||||
#define PB_TEMP_OT_FAULT BIT(7)
|
||||
|
||||
/*
|
||||
* STATUS_FAN
|
||||
*/
|
||||
#define PB_FAN_AIRFLOW_WARNING (1<<0)
|
||||
#define PB_FAN_AIRFLOW_FAULT (1<<1)
|
||||
#define PB_FAN_FAN2_SPEED_OVERRIDE (1<<2)
|
||||
#define PB_FAN_FAN1_SPEED_OVERRIDE (1<<3)
|
||||
#define PB_FAN_FAN2_WARNING (1<<4)
|
||||
#define PB_FAN_FAN1_WARNING (1<<5)
|
||||
#define PB_FAN_FAN2_FAULT (1<<6)
|
||||
#define PB_FAN_FAN1_FAULT (1<<7)
|
||||
#define PB_FAN_AIRFLOW_WARNING BIT(0)
|
||||
#define PB_FAN_AIRFLOW_FAULT BIT(1)
|
||||
#define PB_FAN_FAN2_SPEED_OVERRIDE BIT(2)
|
||||
#define PB_FAN_FAN1_SPEED_OVERRIDE BIT(3)
|
||||
#define PB_FAN_FAN2_WARNING BIT(4)
|
||||
#define PB_FAN_FAN1_WARNING BIT(5)
|
||||
#define PB_FAN_FAN2_FAULT BIT(6)
|
||||
#define PB_FAN_FAN1_FAULT BIT(7)
|
||||
|
||||
/*
|
||||
* CML_FAULT_STATUS
|
||||
*/
|
||||
#define PB_CML_FAULT_OTHER_MEM_LOGIC (1<<0)
|
||||
#define PB_CML_FAULT_OTHER_COMM (1<<1)
|
||||
#define PB_CML_FAULT_PROCESSOR (1<<3)
|
||||
#define PB_CML_FAULT_MEMORY (1<<4)
|
||||
#define PB_CML_FAULT_PACKET_ERROR (1<<5)
|
||||
#define PB_CML_FAULT_INVALID_DATA (1<<6)
|
||||
#define PB_CML_FAULT_INVALID_COMMAND (1<<7)
|
||||
#define PB_CML_FAULT_OTHER_MEM_LOGIC BIT(0)
|
||||
#define PB_CML_FAULT_OTHER_COMM BIT(1)
|
||||
#define PB_CML_FAULT_PROCESSOR BIT(3)
|
||||
#define PB_CML_FAULT_MEMORY BIT(4)
|
||||
#define PB_CML_FAULT_PACKET_ERROR BIT(5)
|
||||
#define PB_CML_FAULT_INVALID_DATA BIT(6)
|
||||
#define PB_CML_FAULT_INVALID_COMMAND BIT(7)
|
||||
|
||||
enum pmbus_sensor_classes {
|
||||
PSC_VOLTAGE_IN = 0,
|
||||
@@ -314,32 +319,34 @@ enum pmbus_sensor_classes {
|
||||
#define PMBUS_PAGES 32 /* Per PMBus specification */
|
||||
|
||||
/* Functionality bit mask */
|
||||
#define PMBUS_HAVE_VIN (1 << 0)
|
||||
#define PMBUS_HAVE_VCAP (1 << 1)
|
||||
#define PMBUS_HAVE_VOUT (1 << 2)
|
||||
#define PMBUS_HAVE_IIN (1 << 3)
|
||||
#define PMBUS_HAVE_IOUT (1 << 4)
|
||||
#define PMBUS_HAVE_PIN (1 << 5)
|
||||
#define PMBUS_HAVE_POUT (1 << 6)
|
||||
#define PMBUS_HAVE_FAN12 (1 << 7)
|
||||
#define PMBUS_HAVE_FAN34 (1 << 8)
|
||||
#define PMBUS_HAVE_TEMP (1 << 9)
|
||||
#define PMBUS_HAVE_TEMP2 (1 << 10)
|
||||
#define PMBUS_HAVE_TEMP3 (1 << 11)
|
||||
#define PMBUS_HAVE_STATUS_VOUT (1 << 12)
|
||||
#define PMBUS_HAVE_STATUS_IOUT (1 << 13)
|
||||
#define PMBUS_HAVE_STATUS_INPUT (1 << 14)
|
||||
#define PMBUS_HAVE_STATUS_TEMP (1 << 15)
|
||||
#define PMBUS_HAVE_STATUS_FAN12 (1 << 16)
|
||||
#define PMBUS_HAVE_STATUS_FAN34 (1 << 17)
|
||||
#define PMBUS_HAVE_VMON (1 << 18)
|
||||
#define PMBUS_HAVE_STATUS_VMON (1 << 19)
|
||||
#define PMBUS_HAVE_VIN BIT(0)
|
||||
#define PMBUS_HAVE_VCAP BIT(1)
|
||||
#define PMBUS_HAVE_VOUT BIT(2)
|
||||
#define PMBUS_HAVE_IIN BIT(3)
|
||||
#define PMBUS_HAVE_IOUT BIT(4)
|
||||
#define PMBUS_HAVE_PIN BIT(5)
|
||||
#define PMBUS_HAVE_POUT BIT(6)
|
||||
#define PMBUS_HAVE_FAN12 BIT(7)
|
||||
#define PMBUS_HAVE_FAN34 BIT(8)
|
||||
#define PMBUS_HAVE_TEMP BIT(9)
|
||||
#define PMBUS_HAVE_TEMP2 BIT(10)
|
||||
#define PMBUS_HAVE_TEMP3 BIT(11)
|
||||
#define PMBUS_HAVE_STATUS_VOUT BIT(12)
|
||||
#define PMBUS_HAVE_STATUS_IOUT BIT(13)
|
||||
#define PMBUS_HAVE_STATUS_INPUT BIT(14)
|
||||
#define PMBUS_HAVE_STATUS_TEMP BIT(15)
|
||||
#define PMBUS_HAVE_STATUS_FAN12 BIT(16)
|
||||
#define PMBUS_HAVE_STATUS_FAN34 BIT(17)
|
||||
#define PMBUS_HAVE_VMON BIT(18)
|
||||
#define PMBUS_HAVE_STATUS_VMON BIT(19)
|
||||
|
||||
enum pmbus_data_format { linear = 0, direct, vid };
|
||||
enum vrm_version { vr11 = 0, vr12 };
|
||||
|
||||
struct pmbus_driver_info {
|
||||
int pages; /* Total number of pages */
|
||||
enum pmbus_data_format format[PSC_NUM_CLASSES];
|
||||
enum vrm_version vrm_version;
|
||||
/*
|
||||
* Support one set of coefficients for each sensor type
|
||||
* Used for chips providing data in direct mode.
|
||||
@@ -380,7 +387,7 @@ struct pmbus_driver_info {
|
||||
|
||||
/* Regulator ops */
|
||||
|
||||
extern struct regulator_ops pmbus_regulator_ops;
|
||||
extern const struct regulator_ops pmbus_regulator_ops;
|
||||
|
||||
/* Macro for filling in array of struct regulator_desc */
|
||||
#define PMBUS_REGULATOR(_name, _id) \
|
||||
@@ -390,6 +397,7 @@ extern struct regulator_ops pmbus_regulator_ops;
|
||||
.of_match = of_match_ptr(_name # _id), \
|
||||
.regulators_node = of_match_ptr("regulators"), \
|
||||
.ops = &pmbus_regulator_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
}
|
||||
|
||||
|
||||
@@ -515,16 +515,24 @@ static long pmbus_reg2data_direct(struct pmbus_data *data,
|
||||
/*
|
||||
* Convert VID sensor values to milli- or micro-units
|
||||
* depending on sensor type.
|
||||
* We currently only support VR11.
|
||||
*/
|
||||
static long pmbus_reg2data_vid(struct pmbus_data *data,
|
||||
struct pmbus_sensor *sensor)
|
||||
{
|
||||
long val = sensor->data;
|
||||
long rv = 0;
|
||||
|
||||
if (val < 0x02 || val > 0xb2)
|
||||
return 0;
|
||||
return DIV_ROUND_CLOSEST(160000 - (val - 2) * 625, 100);
|
||||
switch (data->info->vrm_version) {
|
||||
case vr11:
|
||||
if (val >= 0x02 && val <= 0xb2)
|
||||
rv = DIV_ROUND_CLOSEST(160000 - (val - 2) * 625, 100);
|
||||
break;
|
||||
case vr12:
|
||||
if (val >= 0x01)
|
||||
rv = 250 + (val - 1) * 5;
|
||||
break;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
static long pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor)
|
||||
@@ -1328,6 +1336,10 @@ static const struct pmbus_limit_attr pin_limit_attrs[] = {
|
||||
.reg = PMBUS_VIRT_READ_PIN_AVG,
|
||||
.update = true,
|
||||
.attr = "average",
|
||||
}, {
|
||||
.reg = PMBUS_VIRT_READ_PIN_MIN,
|
||||
.update = true,
|
||||
.attr = "input_lowest",
|
||||
}, {
|
||||
.reg = PMBUS_VIRT_READ_PIN_MAX,
|
||||
.update = true,
|
||||
@@ -1358,6 +1370,10 @@ static const struct pmbus_limit_attr pout_limit_attrs[] = {
|
||||
.reg = PMBUS_VIRT_READ_POUT_AVG,
|
||||
.update = true,
|
||||
.attr = "average",
|
||||
}, {
|
||||
.reg = PMBUS_VIRT_READ_POUT_MIN,
|
||||
.update = true,
|
||||
.attr = "input_lowest",
|
||||
}, {
|
||||
.reg = PMBUS_VIRT_READ_POUT_MAX,
|
||||
.update = true,
|
||||
@@ -1735,6 +1751,11 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data,
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable PEC if the controller supports it */
|
||||
ret = i2c_smbus_read_byte_data(client, PMBUS_CAPABILITY);
|
||||
if (ret >= 0 && (ret & PB_CAPABILITY_ERROR_CHECK))
|
||||
client->flags |= I2C_CLIENT_PEC;
|
||||
|
||||
pmbus_clear_faults(client);
|
||||
|
||||
if (info->identify) {
|
||||
@@ -1796,7 +1817,7 @@ static int pmbus_regulator_disable(struct regulator_dev *rdev)
|
||||
return _pmbus_regulator_on_off(rdev, 0);
|
||||
}
|
||||
|
||||
struct regulator_ops pmbus_regulator_ops = {
|
||||
const struct regulator_ops pmbus_regulator_ops = {
|
||||
.enable = pmbus_regulator_enable,
|
||||
.disable = pmbus_regulator_disable,
|
||||
.is_enabled = pmbus_regulator_is_enabled,
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
@@ -44,16 +45,16 @@ struct zl6100_data {
|
||||
#define ZL6100_MFR_CONFIG 0xd0
|
||||
#define ZL6100_DEVICE_ID 0xe4
|
||||
|
||||
#define ZL6100_MFR_XTEMP_ENABLE (1 << 7)
|
||||
#define ZL6100_MFR_XTEMP_ENABLE BIT(7)
|
||||
|
||||
#define MFR_VMON_OV_FAULT_LIMIT 0xf5
|
||||
#define MFR_VMON_UV_FAULT_LIMIT 0xf6
|
||||
#define MFR_READ_VMON 0xf7
|
||||
|
||||
#define VMON_UV_WARNING (1 << 5)
|
||||
#define VMON_OV_WARNING (1 << 4)
|
||||
#define VMON_UV_FAULT (1 << 1)
|
||||
#define VMON_OV_FAULT (1 << 0)
|
||||
#define VMON_UV_WARNING BIT(5)
|
||||
#define VMON_OV_WARNING BIT(4)
|
||||
#define VMON_UV_FAULT BIT(1)
|
||||
#define VMON_OV_FAULT BIT(0)
|
||||
|
||||
#define ZL6100_WAIT_TIME 1000 /* uS */
|
||||
|
||||
|
||||
+4
-16
@@ -33,6 +33,7 @@
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/bitrev.h>
|
||||
|
||||
/* Commands */
|
||||
#define SHT15_MEASURE_TEMP 0x03
|
||||
@@ -172,19 +173,6 @@ struct sht15_data {
|
||||
atomic_t interrupt_handled;
|
||||
};
|
||||
|
||||
/**
|
||||
* sht15_reverse() - reverse a byte
|
||||
* @byte: byte to reverse.
|
||||
*/
|
||||
static u8 sht15_reverse(u8 byte)
|
||||
{
|
||||
u8 i, c;
|
||||
|
||||
for (c = 0, i = 0; i < 8; i++)
|
||||
c |= (!!(byte & (1 << i))) << (7 - i);
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* sht15_crc8() - compute crc8
|
||||
* @data: sht15 specific data.
|
||||
@@ -196,7 +184,7 @@ static u8 sht15_crc8(struct sht15_data *data,
|
||||
const u8 *value,
|
||||
int len)
|
||||
{
|
||||
u8 crc = sht15_reverse(data->val_status & 0x0F);
|
||||
u8 crc = bitrev8(data->val_status & 0x0F);
|
||||
|
||||
while (len--) {
|
||||
crc = sht15_crc8_table[*value ^ crc];
|
||||
@@ -477,7 +465,7 @@ static int sht15_update_status(struct sht15_data *data)
|
||||
|
||||
if (data->checksumming) {
|
||||
sht15_ack(data);
|
||||
dev_checksum = sht15_reverse(sht15_read_byte(data));
|
||||
dev_checksum = bitrev8(sht15_read_byte(data));
|
||||
checksum_vals[0] = SHT15_READ_STATUS;
|
||||
checksum_vals[1] = status;
|
||||
data->checksum_ok = (sht15_crc8(data, checksum_vals, 2)
|
||||
@@ -864,7 +852,7 @@ static void sht15_bh_read_data(struct work_struct *work_s)
|
||||
*/
|
||||
if (sht15_ack(data))
|
||||
goto wakeup;
|
||||
dev_checksum = sht15_reverse(sht15_read_byte(data));
|
||||
dev_checksum = bitrev8(sht15_read_byte(data));
|
||||
checksum_vals[0] = (data->state == SHT15_READING_TEMP) ?
|
||||
SHT15_MEASURE_TEMP : SHT15_MEASURE_RH;
|
||||
checksum_vals[1] = (u8) (val >> 8);
|
||||
|
||||
Reference in New Issue
Block a user