Commit 22629b6d authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'hwmon-for-linus-v4.3' of...

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
  ...
parents c8192ba4 1ed32160
* 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 ...@@ -3,10 +3,16 @@ ltc2978
Required properties: Required properties:
- compatible: should contain one of: - compatible: should contain one of:
* "lltc,ltc2974" * "lltc,ltc2974"
* "lltc,ltc2975"
* "lltc,ltc2977" * "lltc,ltc2977"
* "lltc,ltc2978" * "lltc,ltc2978"
* "lltc,ltc2980"
* "lltc,ltc3880" * "lltc,ltc3880"
* "lltc,ltc3882"
* "lltc,ltc3883" * "lltc,ltc3883"
* "lltc,ltc3886"
* "lltc,ltc3887"
* "lltc,ltm2987"
* "lltc,ltm4676" * "lltc,ltm4676"
- reg: I2C slave address - reg: I2C slave address
...@@ -17,10 +23,10 @@ Optional properties: ...@@ -17,10 +23,10 @@ Optional properties:
standard binding for regulators; see regulator.txt. standard binding for regulators; see regulator.txt.
Valid names of regulators depend on number of supplies supported per device: Valid names of regulators depend on number of supplies supported per device:
* ltc2974 : vout0 - vout3 * ltc2974, ltc2975 : vout0 - vout3
* ltc2977 : vout0 - vout7 * ltc2977, ltc2980, ltm2987 : vout0 - vout7
* ltc2978 : vout0 - vout7 * ltc2978 : vout0 - vout7
* ltc3880 : vout0 - vout1 * ltc3880, ltc3882, ltc3886 : vout0 - vout1
* ltc3883 : vout0 * ltc3883 : vout0
* ltm4676 : vout0 - vout1 * ltm4676 : vout0 - vout1
......
...@@ -14,6 +14,10 @@ Supported chips: ...@@ -14,6 +14,10 @@ Supported chips:
Prefix: 'adm1276' Prefix: 'adm1276'
Addresses scanned: - Addresses scanned: -
Datasheet: www.analog.com/static/imported-files/data_sheets/ADM1276.pdf 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> Author: Guenter Roeck <linux@roeck-us.net>
...@@ -22,12 +26,12 @@ Description ...@@ -22,12 +26,12 @@ Description
----------- -----------
This driver supports hardware montoring for Analog Devices ADM1075, ADM1275, 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 ADM1075, ADM1275, ADM1276, ADM1293, and ADM1294 are hot-swap controllers that
board to be removed from or inserted into a live backplane. They also feature allow a circuit board to be removed from or inserted into a live backplane.
current and voltage readback via an integrated 12-bit analog-to-digital They also feature current and voltage readback via an integrated 12
converter (ADC), accessed using a PMBus interface. bit analog-to-digital converter (ADC), accessed using a PMBus interface.
The driver is a client driver to the core PMBus driver. Please see The driver is a client driver to the core PMBus driver. Please see
Documentation/hwmon/pmbus for details on PMBus client drivers. Documentation/hwmon/pmbus for details on PMBus client drivers.
...@@ -58,16 +62,16 @@ Sysfs entries ...@@ -58,16 +62,16 @@ Sysfs entries
The following attributes are supported. Limits are read-write, history reset The following attributes are supported. Limits are read-write, history reset
attributes are write-only, all other attributes are read-only. attributes are write-only, all other attributes are read-only.
in1_label "vin1" or "vout1" depending on chip variant and inX_label "vin1" or "vout1" depending on chip variant and
configuration. On ADM1075, vout1 reports the voltage on configuration. On ADM1075, ADM1293, and ADM1294,
the VAUX pin. vout1 reports the voltage on the VAUX pin.
in1_input Measured voltage. inX_input Measured voltage.
in1_min Minimum Voltage. inX_min Minimum Voltage.
in1_max Maximum voltage. inX_max Maximum voltage.
in1_min_alarm Voltage low alarm. inX_min_alarm Voltage low alarm.
in1_max_alarm Voltage high alarm. inX_max_alarm Voltage high alarm.
in1_highest Historical maximum voltage. inX_highest Historical maximum voltage.
in1_reset_history Write any value to reset history. inX_reset_history Write any value to reset history.
curr1_label "iout1" curr1_label "iout1"
curr1_input Measured current. curr1_input Measured current.
...@@ -86,7 +90,9 @@ curr1_reset_history Write any value to reset history. ...@@ -86,7 +90,9 @@ curr1_reset_history Write any value to reset history.
power1_label "pin1" power1_label "pin1"
power1_input Input power. 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. power1_reset_history Write any value to reset history.
Power attributes are supported on ADM1075 and ADM1276 Power attributes are supported on ADM1075, ADM1276,
only. ADM1293, and ADM1294.
...@@ -3,12 +3,13 @@ Kernel driver fam15h_power ...@@ -3,12 +3,13 @@ Kernel driver fam15h_power
Supported chips: Supported chips:
* AMD Family 15h Processors * AMD Family 15h Processors
* AMD Family 16h Processors
Prefix: 'fam15h_power' Prefix: 'fam15h_power'
Addresses scanned: PCI space Addresses scanned: PCI space
Datasheets: Datasheets:
BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors 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> Author: Andreas Herrmann <herrmann.der.user@googlemail.com>
...@@ -16,10 +17,11 @@ Description ...@@ -16,10 +17,11 @@ Description
----------- -----------
This driver permits reading of registers providing power information 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 For AMD Family 15h and 16h processors the following power values can
calculated using different processor northbridge function registers: be calculated using different processor northbridge function
registers:
* BasePwrWatts: Specifies in watts the maximum amount of power * BasePwrWatts: Specifies in watts the maximum amount of power
consumed by the processor for NB and logic external to the core. consumed by the processor for NB and logic external to the core.
......
...@@ -38,6 +38,10 @@ Supported chips: ...@@ -38,6 +38,10 @@ Supported chips:
Prefix: 'it8728' Prefix: 'it8728'
Addresses scanned: from Super I/O config space (8 I/O ports) Addresses scanned: from Super I/O config space (8 I/O ports)
Datasheet: Not publicly available Datasheet: Not publicly available
* IT8732F
Prefix: 'it8732'
Addresses scanned: from Super I/O config space (8 I/O ports)
Datasheet: Not publicly available
* IT8771E * IT8771E
Prefix: 'it8771' Prefix: 'it8771'
Addresses scanned: from Super I/O config space (8 I/O ports) Addresses scanned: from Super I/O config space (8 I/O ports)
...@@ -111,9 +115,9 @@ Description ...@@ -111,9 +115,9 @@ Description
----------- -----------
This driver implements support for the IT8603E, IT8620E, IT8623E, IT8705F, This driver implements support for the IT8603E, IT8620E, IT8623E, IT8705F,
IT8712F, IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8758E, IT8712F, IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8732F,
IT8771E, IT8772E, IT8781F, IT8782F, IT8783E/F, IT8786E, IT8790E, and SiS950 IT8758E, IT8771E, IT8772E, IT8781F, IT8782F, IT8783E/F, IT8786E, IT8790E, and
chips. SiS950 chips.
These chips are 'Super I/O chips', supporting floppy disks, infrared ports, These chips are 'Super I/O chips', supporting floppy disks, infrared ports,
joysticks and other miscellaneous stuff. For hardware monitoring, they joysticks and other miscellaneous stuff. For hardware monitoring, they
...@@ -137,10 +141,10 @@ The IT8716F, IT8718F, IT8720F, IT8721F/IT8758E and later IT8712F revisions ...@@ -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 have support for 2 additional fans. The additional fans are supported by the
driver. driver.
The IT8716F, IT8718F, IT8720F, IT8721F/IT8758E, IT8781F, IT8782F, IT8783E/F, The IT8716F, IT8718F, IT8720F, IT8721F/IT8758E, IT8732F, IT8781F, IT8782F,
and late IT8712F and IT8705F also have optional 16-bit tachometer counters IT8783E/F, and late IT8712F and IT8705F also have optional 16-bit tachometer
for fans 1 to 3. This is better (no more fan clock divider mess) but not counters for fans 1 to 3. This is better (no more fan clock divider mess) but
compatible with the older chips and revisions. The 16-bit tachometer mode 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. is enabled by the driver when one of the above chips is detected.
The IT8726F is just bit enhanced IT8716F with additional hardware The IT8726F is just bit enhanced IT8716F with additional hardware
...@@ -159,6 +163,9 @@ IT8728F. It only supports 16-bit fan mode. ...@@ -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 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 Temperatures are measured in degrees Celsius. An alarm is triggered once
when the Overtemperature Shutdown limit is crossed. when the Overtemperature Shutdown limit is crossed.
...@@ -173,12 +180,14 @@ is done. ...@@ -173,12 +180,14 @@ is done.
Voltage sensors (also known as IN sensors) report their values in volts. An 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 alarm is triggered if the voltage has crossed a programmable minimum or
maximum limit. Note that minimum in this case always means 'closest to maximum limit. Note that minimum in this case always means 'closest to
zero'; this is important for negative voltage measurements. All voltage zero'; this is important for negative voltage measurements. On most chips, all
inputs can measure voltages between 0 and 4.08 volts, with a resolution of voltage inputs can measure voltages between 0 and 4.08 volts, with a resolution
0.016 volt (except IT8603E, IT8721F/IT8758E and IT8728F: 0.012 volt.) The of 0.016 volt. IT8603E, IT8721F/IT8758E and IT8728F can measure between 0 and
battery voltage in8 does not have limit registers. 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
On the IT8603E, IT8721F/IT8758E, IT8781F, IT8782F, and IT8783E/F, some have limit registers.
On the IT8603E, IT8721F/IT8758E, IT8732F, IT8781F, IT8782F, and IT8783E/F, some
voltage inputs are internal and scaled inside the chip: voltage inputs are internal and scaled inside the chip:
* in3 (optional) * in3 (optional)
* in7 (optional for IT8781F, IT8782F, and IT8783E/F) * in7 (optional for IT8781F, IT8782F, and IT8783E/F)
......
...@@ -6,6 +6,10 @@ Supported chips: ...@@ -6,6 +6,10 @@ Supported chips:
Prefix: 'ltc2974' Prefix: 'ltc2974'
Addresses scanned: - Addresses scanned: -
Datasheet: http://www.linear.com/product/ltc2974 Datasheet: http://www.linear.com/product/ltc2974
* Linear Technology LTC2975
Prefix: 'ltc2975'
Addresses scanned: -
Datasheet: http://www.linear.com/product/ltc2975
* Linear Technology LTC2977 * Linear Technology LTC2977
Prefix: 'ltc2977' Prefix: 'ltc2977'
Addresses scanned: - Addresses scanned: -
...@@ -15,14 +19,38 @@ Supported chips: ...@@ -15,14 +19,38 @@ Supported chips:
Addresses scanned: - Addresses scanned: -
Datasheet: http://www.linear.com/product/ltc2978 Datasheet: http://www.linear.com/product/ltc2978
http://www.linear.com/product/ltc2978a http://www.linear.com/product/ltc2978a
* Linear Technology LTC2980
Prefix: 'ltc2980'
Addresses scanned: -
Datasheet: http://www.linear.com/product/ltc2980
* Linear Technology LTC3880 * Linear Technology LTC3880
Prefix: 'ltc3880' Prefix: 'ltc3880'
Addresses scanned: - Addresses scanned: -
Datasheet: http://www.linear.com/product/ltc3880 Datasheet: http://www.linear.com/product/ltc3880
* Linear Technology LTC3882
Prefix: 'ltc3882'
Addresses scanned: -
Datasheet: http://www.linear.com/product/ltc3882
* Linear Technology LTC3883 * Linear Technology LTC3883
Prefix: 'ltc3883' Prefix: 'ltc3883'
Addresses scanned: - Addresses scanned: -
Datasheet: http://www.linear.com/product/ltc3883 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 * Linear Technology LTM4676
Prefix: 'ltm4676' Prefix: 'ltm4676'
Addresses scanned: - Addresses scanned: -
...@@ -34,11 +62,20 @@ Author: Guenter Roeck <linux@roeck-us.net> ...@@ -34,11 +62,20 @@ Author: Guenter Roeck <linux@roeck-us.net>
Description Description
----------- -----------
LTC2974 is a quad digital power supply manager. LTC2978 is an octal power supply LTC2974 and LTC2975 are quad digital power supply managers.
monitor. LTC2977 is a pin compatible replacement for LTC2978. LTC3880 is a dual LTC2978 is an octal power supply monitor.
output poly-phase step-down DC/DC controller. LTC3883 is a single phase LTC2977 is a pin compatible replacement for LTC2978.
step-down DC/DC controller. LTM4676 is a dual 13A or single 26A uModule LTC2980 is a 16-channel Power System Manager, consisting of two LTC2977
regulator. 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 Usage Notes
...@@ -61,26 +98,32 @@ in1_label "vin" ...@@ -61,26 +98,32 @@ in1_label "vin"
in1_input Measured input voltage. in1_input Measured input voltage.
in1_min Minimum input voltage. in1_min Minimum input voltage.
in1_max Maximum 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. 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_crit Critical maximum input voltage.
in1_min_alarm Input voltage low alarm. in1_min_alarm Input voltage low alarm.
in1_max_alarm Input voltage high 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. 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_crit_alarm Input voltage critical high alarm.
in1_lowest Lowest input voltage. in1_lowest Lowest input voltage.
LTC2974, LTC2977, and LTC2978 only. LTC2974, LTC2975, LTC2977, LTC2980, LTC2978, and
LTM2987 only.
in1_highest Highest input voltage. in1_highest Highest input voltage.
in1_reset_history Reset input voltage history. in1_reset_history Reset input voltage history.
in[N]_label "vout[1-8]". in[N]_label "vout[1-8]".
LTC2974: N=2-5 LTC2974, LTC2975: N=2-5
LTC2977: N=2-9 LTC2977, LTC2980, LTM2987: N=2-9
LTC2978: N=2-9 LTC2978: N=2-9
LTC3880, LTM4676: N=2-3 LTC3880, LTC3882, LTC23886 LTC3887, LTM4675, LTM4676:
N=2-3
LTC3883: N=2 LTC3883: N=2
in[N]_input Measured output voltage. in[N]_input Measured output voltage.
in[N]_min Minimum output voltage. in[N]_min Minimum output voltage.
...@@ -91,67 +134,78 @@ in[N]_min_alarm Output voltage low alarm. ...@@ -91,67 +134,78 @@ in[N]_min_alarm Output voltage low alarm.
in[N]_max_alarm Output voltage high alarm. in[N]_max_alarm Output voltage high alarm.
in[N]_lcrit_alarm Output voltage critical low alarm. in[N]_lcrit_alarm Output voltage critical low alarm.
in[N]_crit_alarm Output voltage critical high 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]_highest Highest output voltage.
in[N]_reset_history Reset output voltage history. in[N]_reset_history Reset output voltage history.
temp[N]_input Measured temperature. temp[N]_input Measured temperature.
On LTC2974, temp[1-4] report external temperatures, On LTC2974 and LTC2975, temp[1-4] report external
and temp5 reports the chip temperature. temperatures, and temp5 reports the chip temperature.
On LTC2977 and LTC2978, only one temperature measurement On LTC2977, LTC2980, LTC2978, and LTM2987, only one
is supported and reports the chip temperature. temperature measurement is supported and reports
On LTC3880 and LTM4676, temp1 and temp2 report external the chip temperature.
temperatures, and temp3 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, On LTC3883, temp1 reports an external temperature,
and temp2 reports the chip 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]_max Maximum temperature.
temp[N]_lcrit Critical low temperature. temp[N]_lcrit Critical low temperature.
temp[N]_crit Critical high temperature. temp[N]_crit Critical high temperature.
temp[N]_min_alarm Temperature low alarm. 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]_max_alarm Temperature high alarm.
temp[N]_lcrit_alarm Temperature critical low alarm. temp[N]_lcrit_alarm Temperature critical low alarm.
temp[N]_crit_alarm Temperature critical high alarm. temp[N]_crit_alarm Temperature critical high alarm.
temp[N]_lowest Lowest measured temperature. temp[N]_lowest Lowest measured temperature.
LTC2974, LTC2977, and LTC2978 only. LTC2974, LTC2975, LTC2977, LTM2980, LTC2978, and
Not supported for chip temperature sensor on LTC2974. LTM2987 only.
Not supported for chip temperature sensor on LTC2974 and
LTC2975.
temp[N]_highest Highest measured temperature. Not supported for chip 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 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. power1_input Measured input power.
power[N]_label "pout[1-4]". power[N]_label "pout[1-4]".
LTC2974: N=1-4 LTC2974, LTC2975: N=1-4
LTC2977: Not supported LTC2977, LTC2980, LTM2987: Not supported
LTC2978: Not supported LTC2978: Not supported
LTC3880, LTM4676: N=1-2 LTC3880, LTC3882, LTC3886, LTC3887, LTM4675, LTM4676:
N=1-2
LTC3883: N=2 LTC3883: N=2
power[N]_input Measured output power. 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_input Measured input current.
curr1_max Maximum input current. curr1_max Maximum input current.
curr1_max_alarm Input current high alarm. curr1_max_alarm Input current high alarm.
curr1_highest Highest input current. LTC3883 only. curr1_highest Highest input current. LTC3883 and LTC3886 only.
curr1_reset_history Reset input current history. LTC3883 only. curr1_reset_history Reset input current history. LTC3883 and LTC3886 only.
curr[N]_label "iout[1-4]". curr[N]_label "iout[1-4]".
LTC2974: N=1-4 LTC2974, LTC2975: N=1-4
LTC2977: not supported LTC2977, LTC2980, LTM2987: not supported
LTC2978: not supported LTC2978: not supported
LTC3880, LTM4676: N=2-3 LTC3880, LTC3882, LTC3886, LTC3887, LTM4675, LTM4676:
N=2-3
LTC3883: N=2 LTC3883: N=2
curr[N]_input Measured output current. curr[N]_input Measured output current.
curr[N]_max Maximum output current. curr[N]_max Maximum output current.
curr[N]_crit Critical high 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]_max_alarm Output current high alarm.
curr[N]_crit_alarm Output current critical high alarm. curr[N]_crit_alarm Output current critical high alarm.
curr[N]_lcrit_alarm Output current critical low alarm. LTC2974 only. curr[N]_lcrit_alarm Output current critical low alarm.
curr[N]_lowest Lowest output current. LTC2974 only. LTC2974 and LTC2975 only.
curr[N]_lowest Lowest output current. LTC2974 and LTC2975 only.
curr[N]_highest Highest output current. curr[N]_highest Highest output current.
curr[N]_reset_history Reset output current history. curr[N]_reset_history Reset output current history.
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 ...@@ -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 chip. NCT7802Y supports 6 temperature sensors, 5 voltage sensors, and 3 fan
speed sensors. speed sensors.
The chip also supports intelligent fan speed control. This functionality is Smart Fan™ speed control is available via pwmX_auto_point attributes.
not currently supported by the driver.
Tested Boards and BIOS Versions Tested Boards and BIOS Versions
------------------------------- -------------------------------
......
...@@ -23,11 +23,15 @@ Supported chips: ...@@ -23,11 +23,15 @@ Supported chips:
http://www.lineagepower.com/oem/pdf/PDT012A0X.pdf http://www.lineagepower.com/oem/pdf/PDT012A0X.pdf
http://www.lineagepower.com/oem/pdf/UDT020A0X.pdf http://www.lineagepower.com/oem/pdf/UDT020A0X.pdf
http://www.lineagepower.com/oem/pdf/MDT040A0X.pdf http://www.lineagepower.com/oem/pdf/MDT040A0X.pdf
* Texas Instruments TPS40400 * Texas Instruments TPS40400, TPS544B20, TPS544B25, TPS544C20, TPS544C25
Prefixes: 'tps40400' Prefixes: 'tps40400', 'tps544b20', 'tps544b25', 'tps544c20', 'tps544c25'
Addresses scanned: - Addresses scanned: -
Datasheets: Datasheets:
http://www.ti.com/lit/gpn/tps40400 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 * Generic PMBus devices
Prefix: 'pmbus' Prefix: 'pmbus'
Addresses scanned: - Addresses scanned: -
......
...@@ -6549,6 +6549,13 @@ S: Maintained ...@@ -6549,6 +6549,13 @@ S: Maintained
F: Documentation/hwmon/max16065 F: Documentation/hwmon/max16065
F: drivers/hwmon/max16065.c 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 MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER
M: "Hans J. Koch" <hjk@hansjkoch.de> M: "Hans J. Koch" <hjk@hansjkoch.de>
L: lm-sensors@lm-sensors.org L: lm-sensors@lm-sensors.org
......
...@@ -609,8 +609,8 @@ config SENSORS_IT87 ...@@ -609,8 +609,8 @@ config SENSORS_IT87
depends on !PPC depends on !PPC
select HWMON_VID select HWMON_VID
help help
If you say yes here you get support for ITE IT8705F, IT8712F, If you say yes here you get support for ITE IT8705F, IT8712F, IT8716F,
IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8758E, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8732F, IT8758E,
IT8771E, IT8772E, IT8781F, IT8782F, IT8783E/F, IT8786E, IT8790E, IT8771E, IT8772E, IT8781F, IT8782F, IT8783E/F, IT8786E, IT8790E,
IT8603E, IT8620E, and IT8623E sensor chips, and the SiS950 clone. IT8603E, IT8620E, and IT8623E sensor chips, and the SiS950 clone.
......
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#define SIO_F71808A_ID 0x1001 /* Chipset ID */ #define SIO_F71808A_ID 0x1001 /* Chipset ID */
#define SIO_F71858_ID 0x0507 /* Chipset ID */ #define SIO_F71858_ID 0x0507 /* Chipset ID */
#define SIO_F71862_ID 0x0601 /* 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_F71869_ID 0x0814 /* Chipset ID */
#define SIO_F71869A_ID 0x1007 /* Chipset ID */ #define SIO_F71869A_ID 0x1007 /* Chipset ID */
#define SIO_F71882_ID 0x0541 /* Chipset ID */ #define SIO_F71882_ID 0x0541 /* Chipset ID */
...@@ -58,7 +59,9 @@ ...@@ -58,7 +59,9 @@
#define SIO_F71889E_ID 0x0909 /* Chipset ID */ #define SIO_F71889E_ID 0x0909 /* Chipset ID */
#define SIO_F71889A_ID 0x1005 /* Chipset ID */ #define SIO_F71889A_ID 0x1005 /* Chipset ID */
#define SIO_F8000_ID 0x0581 /* 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_F81865_ID 0x0704 /* Chipset ID */
#define SIO_F81866_ID 0x1010 /* Chipset ID */
#define REGION_LENGTH 8 #define REGION_LENGTH 8
#define ADDR_REG_OFFSET 5 #define ADDR_REG_OFFSET 5
...@@ -69,6 +72,10 @@ ...@@ -69,6 +72,10 @@
#define F71882FG_REG_IN(nr) (0x20 + (nr)) #define F71882FG_REG_IN(nr) (0x20 + (nr))
#define F71882FG_REG_IN1_HIGH 0x32 /* f7188x only */ #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(nr) (0xA0 + (16 * (nr)))
#define F71882FG_REG_FAN_TARGET(nr) (0xA2 + (16 * (nr))) #define F71882FG_REG_FAN_TARGET(nr) (0xA2 + (16 * (nr)))
#define F71882FG_REG_FAN_FULL_SPEED(nr) (0xA4 + (16 * (nr))) #define F71882FG_REG_FAN_FULL_SPEED(nr) (0xA4 + (16 * (nr)))
...@@ -101,7 +108,7 @@ ...@@ -101,7 +108,7 @@
#define F71882FG_REG_START 0x01 #define F71882FG_REG_START 0x01
#define F71882FG_MAX_INS 9 #define F71882FG_MAX_INS 11
#define FAN_MIN_DETECT 366 /* Lowest detectable fanspeed */ #define FAN_MIN_DETECT 366 /* Lowest detectable fanspeed */
...@@ -109,14 +116,16 @@ static unsigned short force_id; ...@@ -109,14 +116,16 @@ static unsigned short force_id;
module_param(force_id, ushort, 0); module_param(force_id, ushort, 0);
MODULE_PARM_DESC(force_id, "Override the detected device ID"); MODULE_PARM_DESC(force_id, "Override the detected device ID");
enum chips { f71808e, f71808a, f71858fg, f71862fg, f71869, f71869a, f71882fg, enum chips { f71808e, f71808a, f71858fg, f71862fg, f71868a, f71869, f71869a,
f71889fg, f71889ed, f71889a, f8000, f81865f }; f71882fg, f71889fg, f71889ed, f71889a, f8000, f81768d, f81865f,
f81866a};
static const char *const f71882fg_names[] = { static const char *const f71882fg_names[] = {
"f71808e", "f71808e",
"f71808a", "f71808a",
"f71858fg", "f71858fg",
"f71862fg", "f71862fg",
"f71868a",
"f71869", /* Both f71869f and f71869e, reg. compatible and same id */ "f71869", /* Both f71869f and f71869e, reg. compatible and same id */
"f71869a", "f71869a",
"f71882fg", "f71882fg",
...@@ -124,22 +133,27 @@ static const char *const f71882fg_names[] = { ...@@ -124,22 +133,27 @@ static const char *const f71882fg_names[] = {
"f71889ed", "f71889ed",
"f71889a", "f71889a",
"f8000", "f8000",
"f81768d",
"f81865f", "f81865f",
"f81866a",
}; };
static const char f71882fg_has_in[][F71882FG_MAX_INS] = { static const char f71882fg_has_in[][F71882FG_MAX_INS] = {
[f71808e] = { 1, 1, 1, 1, 1, 1, 0, 1, 1 }, [f71808e] = { 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0 },
[f71808a] = { 1, 1, 1, 1, 0, 0, 0, 1, 1 }, [f71808a] = { 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0 },
[f71858fg] = { 1, 1, 1, 0, 0, 0, 0, 0, 0 }, [f71858fg] = { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
[f71862fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, [f71862fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
[f71869] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, [f71868a] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
[f71869a] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, [f71869] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
[f71882fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, [f71869a] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
[f71889fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, [f71882fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
[f71889ed] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, [f71889fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
[f71889a] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, [f71889ed] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
[f8000] = { 1, 1, 1, 0, 0, 0, 0, 0, 0 }, [f71889a] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
[f81865f] = { 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[] = { static const char f71882fg_has_in1_alarm[] = {
...@@ -147,6 +161,7 @@ static const char f71882fg_has_in1_alarm[] = { ...@@ -147,6 +161,7 @@ static const char f71882fg_has_in1_alarm[] = {
[f71808a] = 0, [f71808a] = 0,
[f71858fg] = 0, [f71858fg] = 0,
[f71862fg] = 0, [f71862fg] = 0,
[f71868a] = 0,
[f71869] = 0, [f71869] = 0,
[f71869a] = 0, [f71869a] = 0,
[f71882fg] = 1, [f71882fg] = 1,
...@@ -154,7 +169,9 @@ static const char f71882fg_has_in1_alarm[] = { ...@@ -154,7 +169,9 @@ static const char f71882fg_has_in1_alarm[] = {
[f71889ed] = 1, [f71889ed] = 1,
[f71889a] = 1, [f71889a] = 1,
[f8000] = 0, [f8000] = 0,
[f81768d] = 1,
[f81865f] = 1, [f81865f] = 1,
[f81866a] = 1,
}; };
static const char f71882fg_fan_has_beep[] = { static const char f71882fg_fan_has_beep[] = {
...@@ -162,6 +179,7 @@ static const char f71882fg_fan_has_beep[] = { ...@@ -162,6 +179,7 @@ static const char f71882fg_fan_has_beep[] = {
[f71808a] = 0, [f71808a] = 0,
[f71858fg] = 0, [f71858fg] = 0,
[f71862fg] = 1, [f71862fg] = 1,
[f71868a] = 1,
[f71869] = 1, [f71869] = 1,
[f71869a] = 1, [f71869a] = 1,
[f71882fg] = 1, [f71882fg] = 1,
...@@ -169,7 +187,9 @@ static const char f71882fg_fan_has_beep[] = { ...@@ -169,7 +187,9 @@ static const char f71882fg_fan_has_beep[] = {
[f71889ed] = 1, [f71889ed] = 1,
[f71889a] = 1, [f71889a] = 1,
[f8000] = 0, [f8000] = 0,
[f81768d] = 1,
[f81865f] = 1, [f81865f] = 1,
[f81866a] = 1,
}; };
static const char f71882fg_nr_fans[] = { static const char f71882fg_nr_fans[] = {
...@@ -177,6 +197,7 @@ 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 */ [f71808a] = 2, /* +1 fan which is monitor + simple pwm only */
[f71858fg] = 3, [f71858fg] = 3,
[f71862fg] = 3, [f71862fg] = 3,
[f71868a] = 3,
[f71869] = 3, [f71869] = 3,
[f71869a] = 3, [f71869a] = 3,
[f71882fg] = 4, [f71882fg] = 4,
...@@ -184,7 +205,9 @@ static const char f71882fg_nr_fans[] = { ...@@ -184,7 +205,9 @@ static const char f71882fg_nr_fans[] = {
[f71889ed] = 3, [f71889ed] = 3,
[f71889a] = 3, [f71889a] = 3,
[f8000] = 3, /* +1 fan which is monitor only */ [f8000] = 3, /* +1 fan which is monitor only */
[f81768d] = 3,
[f81865f] = 2, [f81865f] = 2,
[f81866a] = 3,
}; };
static const char f71882fg_temp_has_beep[] = { static const char f71882fg_temp_has_beep[] = {
...@@ -192,6 +215,7 @@ static const char f71882fg_temp_has_beep[] = { ...@@ -192,6 +215,7 @@ static const char f71882fg_temp_has_beep[] = {
[f71808a] = 1, [f71808a] = 1,
[f71858fg] = 0, [f71858fg] = 0,
[f71862fg] = 1, [f71862fg] = 1,
[f71868a] = 1,
[f71869] = 1, [f71869] = 1,
[f71869a] = 1, [f71869a] = 1,
[f71882fg] = 1, [f71882fg] = 1,
...@@ -199,7 +223,9 @@ static const char f71882fg_temp_has_beep[] = { ...@@ -199,7 +223,9 @@ static const char f71882fg_temp_has_beep[] = {
[f71889ed] = 1, [f71889ed] = 1,
[f71889a] = 1, [f71889a] = 1,
[f8000] = 0, [f8000] = 0,
[f81768d] = 1,
[f81865f] = 1, [f81865f] = 1,
[f81866a] = 1,
}; };
static const char f71882fg_nr_temps[] = { static const char f71882fg_nr_temps[] = {
...@@ -207,6 +233,7 @@ static const char f71882fg_nr_temps[] = { ...@@ -207,6 +233,7 @@ static const char f71882fg_nr_temps[] = {
[f71808a] = 2, [f71808a] = 2,
[f71858fg] = 3, [f71858fg] = 3,
[f71862fg] = 3, [f71862fg] = 3,
[f71868a] = 3,
[f71869] = 3, [f71869] = 3,
[f71869a] = 3, [f71869a] = 3,
[f71882fg] = 3, [f71882fg] = 3,
...@@ -214,7 +241,9 @@ static const char f71882fg_nr_temps[] = { ...@@ -214,7 +241,9 @@ static const char f71882fg_nr_temps[] = {
[f71889ed] = 3, [f71889ed] = 3,
[f71889a] = 3, [f71889a] = 3,
[f8000] = 3, [f8000] = 3,
[f81768d] = 3,
[f81865f] = 2, [f81865f] = 2,
[f81866a] = 3,
}; };
static struct platform_device *f71882fg_pdev; static struct platform_device *f71882fg_pdev;
...@@ -490,6 +519,23 @@ static struct sensor_device_attribute_2 fxxxx_temp_beep_attr[3][2] = { { ...@@ -490,6 +519,23 @@ static struct sensor_device_attribute_2 fxxxx_temp_beep_attr[3][2] = { {
store_temp_beep, 0, 7), 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 * Temp attr for the f8000
* Note on the f8000 temp_ovt (crit) is used as max, and temp_high (max) * 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[] = { ...@@ -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(in6_input, S_IRUGO, show_in, NULL, 0, 6),
SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7), 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(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 */ /* For models with in1 alarm capability */
...@@ -1170,10 +1218,21 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) ...@@ -1170,10 +1218,21 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
if (time_after(jiffies, data->last_limits + 60 * HZ) || if (time_after(jiffies, data->last_limits + 60 * HZ) ||
!data->valid) { !data->valid) {
if (f71882fg_has_in1_alarm[data->type]) { if (f71882fg_has_in1_alarm[data->type]) {
data->in1_max = if (data->type == f81866a) {
f71882fg_read8(data, F71882FG_REG_IN1_HIGH); data->in1_max =
data->in_beep = f71882fg_read8(data,
f71882fg_read8(data, F71882FG_REG_IN_BEEP); 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*/ /* Get High & boundary temps*/
...@@ -1297,9 +1356,16 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) ...@@ -1297,9 +1356,16 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
data->fan[3] = f71882fg_read16(data, data->fan[3] = f71882fg_read16(data,
F71882FG_REG_FAN(3)); F71882FG_REG_FAN(3));
if (f71882fg_has_in1_alarm[data->type]) if (f71882fg_has_in1_alarm[data->type]) {
data->in_status = f71882fg_read8(data, 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); F71882FG_REG_IN_STATUS);
}
for (nr = 0; nr < F71882FG_MAX_INS; nr++) for (nr = 0; nr < F71882FG_MAX_INS; nr++)
if (f71882fg_has_in[data->type][nr]) if (f71882fg_has_in[data->type][nr])
data->in[nr] = f71882fg_read8(data, data->in[nr] = f71882fg_read8(data,
...@@ -1440,7 +1506,10 @@ static ssize_t store_in_max(struct device *dev, struct device_attribute ...@@ -1440,7 +1506,10 @@ static ssize_t store_in_max(struct device *dev, struct device_attribute
val = clamp_val(val, 0, 255); val = clamp_val(val, 0, 255);
mutex_lock(&data->update_lock); 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; data->in1_max = val;
mutex_unlock(&data->update_lock); mutex_unlock(&data->update_lock);
...@@ -1471,13 +1540,20 @@ static ssize_t store_in_beep(struct device *dev, struct device_attribute ...@@ -1471,13 +1540,20 @@ static ssize_t store_in_beep(struct device *dev, struct device_attribute
return err; return err;
mutex_lock(&data->update_lock); 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) if (val)
data->in_beep |= 1 << nr; data->in_beep |= 1 << nr;
else else
data->in_beep &= ~(1 << nr); 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); mutex_unlock(&data->update_lock);
return count; return count;
...@@ -2270,6 +2346,7 @@ static int f71882fg_probe(struct platform_device *pdev) ...@@ -2270,6 +2346,7 @@ static int f71882fg_probe(struct platform_device *pdev)
int nr_fans = f71882fg_nr_fans[sio_data->type]; int nr_fans = f71882fg_nr_fans[sio_data->type];
int nr_temps = f71882fg_nr_temps[sio_data->type]; int nr_temps = f71882fg_nr_temps[sio_data->type];
int err, i; int err, i;
int size;
u8 start_reg, reg; u8 start_reg, reg;
data = devm_kzalloc(&pdev->dev, sizeof(struct f71882fg_data), data = devm_kzalloc(&pdev->dev, sizeof(struct f71882fg_data),
...@@ -2280,7 +2357,8 @@ static int f71882fg_probe(struct platform_device *pdev) ...@@ -2280,7 +2357,8 @@ static int f71882fg_probe(struct platform_device *pdev)
data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start; data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
data->type = sio_data->type; data->type = sio_data->type;
data->temp_start = 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); mutex_init(&data->update_lock);
platform_set_drvdata(pdev, data); platform_set_drvdata(pdev, data);
...@@ -2322,6 +2400,11 @@ static int f71882fg_probe(struct platform_device *pdev) ...@@ -2322,6 +2400,11 @@ static int f71882fg_probe(struct platform_device *pdev)
f8000_temp_attr, f8000_temp_attr,
ARRAY_SIZE(f8000_temp_attr)); ARRAY_SIZE(f8000_temp_attr));
break; break;
case f81866a:
err = f71882fg_create_sysfs_files(pdev,
f71858fg_temp_attr,
ARRAY_SIZE(f71858fg_temp_attr));
break;
default: default:
err = f71882fg_create_sysfs_files(pdev, err = f71882fg_create_sysfs_files(pdev,
&fxxxx_temp_attr[0][0], &fxxxx_temp_attr[0][0],
...@@ -2331,10 +2414,18 @@ static int f71882fg_probe(struct platform_device *pdev) ...@@ -2331,10 +2414,18 @@ static int f71882fg_probe(struct platform_device *pdev)
goto exit_unregister_sysfs; goto exit_unregister_sysfs;
if (f71882fg_temp_has_beep[data->type]) { if (f71882fg_temp_has_beep[data->type]) {
err = f71882fg_create_sysfs_files(pdev, if (data->type == f81866a) {
&fxxxx_temp_beep_attr[0][0], size = ARRAY_SIZE(f81866_temp_beep_attr[0]);
ARRAY_SIZE(fxxxx_temp_beep_attr[0]) err = f71882fg_create_sysfs_files(pdev,
* nr_temps); &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) if (err)
goto exit_unregister_sysfs; goto exit_unregister_sysfs;
} }
...@@ -2451,15 +2542,27 @@ static int f71882fg_remove(struct platform_device *pdev) ...@@ -2451,15 +2542,27 @@ static int f71882fg_remove(struct platform_device *pdev)
f8000_temp_attr, f8000_temp_attr,
ARRAY_SIZE(f8000_temp_attr)); ARRAY_SIZE(f8000_temp_attr));
break; break;
case f81866a:
f71882fg_remove_sysfs_files(pdev,
f71858fg_temp_attr,
ARRAY_SIZE(f71858fg_temp_attr));
break;
default: default:
f71882fg_remove_sysfs_files(pdev, f71882fg_remove_sysfs_files(pdev,
&fxxxx_temp_attr[0][0], &fxxxx_temp_attr[0][0],
ARRAY_SIZE(fxxxx_temp_attr[0]) * nr_temps); ARRAY_SIZE(fxxxx_temp_attr[0]) * nr_temps);
} }
if (f71882fg_temp_has_beep[data->type]) { if (f71882fg_temp_has_beep[data->type]) {
f71882fg_remove_sysfs_files(pdev, if (data->type == f81866a)
&fxxxx_temp_beep_attr[0][0], f71882fg_remove_sysfs_files(pdev,
ARRAY_SIZE(fxxxx_temp_beep_attr[0]) * nr_temps); &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++) { 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) ...@@ -2551,6 +2654,9 @@ static int __init f71882fg_find(int sioaddr, struct f71882fg_sio_data *sio_data)
case SIO_F71862_ID: case SIO_F71862_ID:
sio_data->type = f71862fg; sio_data->type = f71862fg;
break; break;
case SIO_F71868_ID:
sio_data->type = f71868a;
break;
case SIO_F71869_ID: case SIO_F71869_ID:
sio_data->type = f71869; sio_data->type = f71869;
break; break;
...@@ -2572,9 +2678,15 @@ static int __init f71882fg_find(int sioaddr, struct f71882fg_sio_data *sio_data) ...@@ -2572,9 +2678,15 @@ static int __init f71882fg_find(int sioaddr, struct f71882fg_sio_data *sio_data)
case SIO_F8000_ID: case SIO_F8000_ID:
sio_data->type = f8000; sio_data->type = f8000;
break; break;
case SIO_F81768D_ID:
sio_data->type = f81768d;
break;
case SIO_F81865_ID: case SIO_F81865_ID:
sio_data->type = f81865f; sio_data->type = f81865f;
break; break;
case SIO_F81866_ID:
sio_data->type = f81866a;
break;
default: default:
pr_info("Unsupported Fintek device: %04x\n", pr_info("Unsupported Fintek device: %04x\n",
(unsigned int)devid); (unsigned int)devid);
......
...@@ -46,6 +46,7 @@ struct fam15h_power_data { ...@@ -46,6 +46,7 @@ struct fam15h_power_data {
unsigned int tdp_to_watts; unsigned int tdp_to_watts;
unsigned int base_tdp; unsigned int base_tdp;
unsigned int processor_pwr_watts; unsigned int processor_pwr_watts;
unsigned int cpu_pwr_sample_ratio;
}; };
static ssize_t show_power(struct device *dev, static ssize_t show_power(struct device *dev,
...@@ -59,8 +60,19 @@ 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), pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5),
REG_TDP_RUNNING_AVERAGE, &val); 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; running_avg_range = (val & 0xf) + 1;
pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5), 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 = { ...@@ -117,7 +129,7 @@ static const struct attribute_group fam15h_power_group = {
}; };
__ATTRIBUTE_GROUPS(fam15h_power); __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; u32 val;
...@@ -177,7 +189,7 @@ static int fam15h_power_resume(struct pci_dev *pdev) ...@@ -177,7 +189,7 @@ static int fam15h_power_resume(struct pci_dev *pdev)
static void fam15h_power_init_data(struct pci_dev *f4, static void fam15h_power_init_data(struct pci_dev *f4,
struct fam15h_power_data *data) struct fam15h_power_data *data)
{ {
u32 val; u32 val, eax, ebx, ecx, edx;
u64 tmp; u64 tmp;
pci_read_config_dword(f4, REG_PROCESSOR_TDP, &val); pci_read_config_dword(f4, REG_PROCESSOR_TDP, &val);
...@@ -198,6 +210,19 @@ static void fam15h_power_init_data(struct pci_dev *f4, ...@@ -198,6 +210,19 @@ static void fam15h_power_init_data(struct pci_dev *f4,
/* convert to microWatt */ /* convert to microWatt */
data->processor_pwr_watts = (tmp * 15625) >> 10; 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, static int fam15h_power_probe(struct pci_dev *pdev,
...@@ -214,7 +239,7 @@ 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); tweak_runavg_range(pdev);
if (!fam15h_power_is_internal_node0(pdev)) if (!should_load_on_this_node(pdev))
return -ENODEV; return -ENODEV;
data = devm_kzalloc(dev, sizeof(struct fam15h_power_data), GFP_KERNEL); data = devm_kzalloc(dev, sizeof(struct fam15h_power_data), GFP_KERNEL);
...@@ -233,6 +258,7 @@ static int fam15h_power_probe(struct pci_dev *pdev, ...@@ -233,6 +258,7 @@ static int fam15h_power_probe(struct pci_dev *pdev,
static const struct pci_device_id fam15h_power_id_table[] = { 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_NB_F4) },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M30H_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_NB_F4) },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_M30H_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) ...@@ -1113,7 +1113,6 @@ static int g762_remove(struct i2c_client *client)
static struct i2c_driver g762_driver = { static struct i2c_driver g762_driver = {
.driver = { .driver = {
.name = DRVNAME, .name = DRVNAME,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(g762_dt_match), .of_match_table = of_match_ptr(g762_dt_match),
}, },
.probe = g762_probe, .probe = g762_probe,
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
* IT8721F Super I/O chip w/LPC interface * IT8721F Super I/O chip w/LPC interface
* IT8726F Super I/O chip w/LPC interface * IT8726F Super I/O chip w/LPC interface
* IT8728F 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 * IT8758E Super I/O chip w/LPC interface
* IT8771E Super I/O chip w/LPC interface * IT8771E Super I/O chip w/LPC interface
* IT8772E Super I/O chip w/LPC interface * IT8772E Super I/O chip w/LPC interface
...@@ -69,8 +70,9 @@ ...@@ -69,8 +70,9 @@
#define DRVNAME "it87" #define DRVNAME "it87"
enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728, it8771, enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728, it8732,
it8772, it8781, it8782, it8783, it8786, it8790, it8603, it8620 }; it8771, it8772, it8781, it8782, it8783, it8786, it8790, it8603,
it8620 };
static unsigned short force_id; static unsigned short force_id;
module_param(force_id, ushort, 0); module_param(force_id, ushort, 0);
...@@ -148,6 +150,7 @@ static inline void superio_exit(void) ...@@ -148,6 +150,7 @@ static inline void superio_exit(void)
#define IT8721F_DEVID 0x8721 #define IT8721F_DEVID 0x8721
#define IT8726F_DEVID 0x8726 #define IT8726F_DEVID 0x8726
#define IT8728F_DEVID 0x8728 #define IT8728F_DEVID 0x8728
#define IT8732F_DEVID 0x8732
#define IT8771E_DEVID 0x8771 #define IT8771E_DEVID 0x8771
#define IT8772E_DEVID 0x8772 #define IT8772E_DEVID 0x8772
#define IT8781F_DEVID 0x8781 #define IT8781F_DEVID 0x8781
...@@ -265,6 +268,7 @@ struct it87_devices { ...@@ -265,6 +268,7 @@ struct it87_devices {
#define FEAT_VID (1 << 9) /* Set if chip supports VID */ #define FEAT_VID (1 << 9) /* Set if chip supports VID */
#define FEAT_IN7_INTERNAL (1 << 10) /* Set if in7 is internal */ #define FEAT_IN7_INTERNAL (1 << 10) /* Set if in7 is internal */
#define FEAT_SIX_FANS (1 << 11) /* Supports six fans */ #define FEAT_SIX_FANS (1 << 11) /* Supports six fans */
#define FEAT_10_9MV_ADC (1 << 12)
static const struct it87_devices it87_devices[] = { static const struct it87_devices it87_devices[] = {
[it87] = { [it87] = {
...@@ -315,6 +319,15 @@ static const struct it87_devices it87_devices[] = { ...@@ -315,6 +319,15 @@ static const struct it87_devices it87_devices[] = {
| FEAT_IN7_INTERNAL, | FEAT_IN7_INTERNAL,
.peci_mask = 0x07, .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] = { [it8771] = {
.name = "it8771", .name = "it8771",
.suffix = "E", .suffix = "E",
...@@ -391,6 +404,7 @@ static const struct it87_devices it87_devices[] = { ...@@ -391,6 +404,7 @@ static const struct it87_devices it87_devices[] = {
#define has_16bit_fans(data) ((data)->features & FEAT_16BIT_FANS) #define has_16bit_fans(data) ((data)->features & FEAT_16BIT_FANS)
#define has_12mv_adc(data) ((data)->features & FEAT_12MV_ADC) #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_newer_autopwm(data) ((data)->features & FEAT_NEWER_AUTOPWM)
#define has_old_autopwm(data) ((data)->features & FEAT_OLD_AUTOPWM) #define has_old_autopwm(data) ((data)->features & FEAT_OLD_AUTOPWM)
#define has_temp_offset(data) ((data)->features & FEAT_TEMP_OFFSET) #define has_temp_offset(data) ((data)->features & FEAT_TEMP_OFFSET)
...@@ -475,7 +489,14 @@ struct it87_data { ...@@ -475,7 +489,14 @@ struct it87_data {
static int adc_lsb(const struct it87_data *data, int nr) 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)) if (data->in_scaled & (1 << nr))
lsb <<= 1; lsb <<= 1;
return lsb; return lsb;
...@@ -483,13 +504,13 @@ static int adc_lsb(const struct it87_data *data, int nr) ...@@ -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) 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); return clamp_val(val, 0, 255);
} }
static int in_from_reg(const struct it87_data *data, int nr, int val) 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) 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, ...@@ -1515,9 +1536,14 @@ static ssize_t show_label(struct device *dev, struct device_attribute *attr,
}; };
struct it87_data *data = dev_get_drvdata(dev); struct it87_data *data = dev_get_drvdata(dev);
int nr = to_sensor_dev_attr(attr)->index; int nr = to_sensor_dev_attr(attr)->index;
const char *label;
return sprintf(buf, "%s\n", has_12mv_adc(data) ? labels_it8721[nr] if (has_12mv_adc(data) || has_10_9mv_adc(data))
: labels[nr]); 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(in3_label, S_IRUGO, show_label, NULL, 0);
static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 1); static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 1);
...@@ -1853,6 +1879,9 @@ static int __init it87_find(unsigned short *address, ...@@ -1853,6 +1879,9 @@ static int __init it87_find(unsigned short *address,
case IT8728F_DEVID: case IT8728F_DEVID:
sio_data->type = it8728; sio_data->type = it8728;
break; break;
case IT8732F_DEVID:
sio_data->type = it8732;
break;
case IT8771E_DEVID: case IT8771E_DEVID:
sio_data->type = it8771; sio_data->type = it8771;
break; break;
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/of_device.h>
#define DRVNAME "lm70" #define DRVNAME "lm70"
...@@ -130,11 +131,41 @@ ATTRIBUTE_GROUPS(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) 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 device *hwmon_dev;
struct lm70 *p_lm70; 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 */ /* signaling is SPI_MODE_0 */
if (spi->mode & (SPI_CPOL | SPI_CPHA)) if (spi->mode & (SPI_CPOL | SPI_CPHA))
...@@ -169,6 +200,7 @@ static struct spi_driver lm70_driver = { ...@@ -169,6 +200,7 @@ static struct spi_driver lm70_driver = {
.driver = { .driver = {
.name = "lm70", .name = "lm70",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = of_match_ptr(lm70_of_ids),
}, },
.id_table = lm70_ids, .id_table = lm70_ids,
.probe = lm70_probe, .probe = lm70_probe,
......
...@@ -49,10 +49,13 @@ static const u8 REG_VOLTAGE_LIMIT_MSB_SHIFT[2][5] = { ...@@ -49,10 +49,13 @@ static const u8 REG_VOLTAGE_LIMIT_MSB_SHIFT[2][5] = {
#define REG_VOLTAGE_LOW 0x0f #define REG_VOLTAGE_LOW 0x0f
#define REG_FANCOUNT_LOW 0x13 #define REG_FANCOUNT_LOW 0x13
#define REG_START 0x21 #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_PECI_ENABLE 0x23
#define REG_FAN_ENABLE 0x24 #define REG_FAN_ENABLE 0x24
#define REG_VMON_ENABLE 0x25 #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_VENDOR_ID 0xfd
#define REG_CHIP_ID 0xfe #define REG_CHIP_ID 0xfe
#define REG_VERSION_ID 0xff #define REG_VERSION_ID 0xff
...@@ -66,6 +69,129 @@ struct nct7802_data { ...@@ -66,6 +69,129 @@ struct nct7802_data {
struct mutex access_lock; /* for multi-byte read and write operations */ 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, &regval);
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), &reg);
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, static int nct7802_read_temp(struct nct7802_data *data,
u8 reg_temp, u8 reg_temp_low, int *temp) 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, ...@@ -377,6 +503,8 @@ store_beep(struct device *dev, struct device_attribute *attr, const char *buf,
return err ? : count; 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, static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0x01,
REG_TEMP_LSB); REG_TEMP_LSB);
static SENSOR_DEVICE_ATTR_2(temp1_min, S_IRUGO | S_IWUSR, show_temp, 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, ...@@ -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, static SENSOR_DEVICE_ATTR_2(temp1_crit, S_IRUGO | S_IWUSR, show_temp,
store_temp, 0x3a, 0); 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, static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0x02,
REG_TEMP_LSB); REG_TEMP_LSB);
static SENSOR_DEVICE_ATTR_2(temp2_min, S_IRUGO | S_IWUSR, show_temp, 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, ...@@ -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, static SENSOR_DEVICE_ATTR_2(temp2_crit, S_IRUGO | S_IWUSR, show_temp,
store_temp, 0x3b, 0); 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, static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0x03,
REG_TEMP_LSB); REG_TEMP_LSB);
static SENSOR_DEVICE_ATTR_2(temp3_min, S_IRUGO | S_IWUSR, show_temp, 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, ...@@ -475,6 +607,7 @@ static SENSOR_DEVICE_ATTR_2(temp6_beep, S_IRUGO | S_IWUSR, show_beep,
store_beep, 0x5c, 5); store_beep, 0x5c, 5);
static struct attribute *nct7802_temp_attrs[] = { 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_input.dev_attr.attr,
&sensor_dev_attr_temp1_min.dev_attr.attr, &sensor_dev_attr_temp1_min.dev_attr.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr, &sensor_dev_attr_temp1_max.dev_attr.attr,
...@@ -485,7 +618,8 @@ static struct attribute *nct7802_temp_attrs[] = { ...@@ -485,7 +618,8 @@ static struct attribute *nct7802_temp_attrs[] = {
&sensor_dev_attr_temp1_fault.dev_attr.attr, &sensor_dev_attr_temp1_fault.dev_attr.attr,
&sensor_dev_attr_temp1_beep.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_min.dev_attr.attr,
&sensor_dev_attr_temp2_max.dev_attr.attr, &sensor_dev_attr_temp2_max.dev_attr.attr,
&sensor_dev_attr_temp2_crit.dev_attr.attr, &sensor_dev_attr_temp2_crit.dev_attr.attr,
...@@ -495,7 +629,8 @@ static struct attribute *nct7802_temp_attrs[] = { ...@@ -495,7 +629,8 @@ static struct attribute *nct7802_temp_attrs[] = {
&sensor_dev_attr_temp2_fault.dev_attr.attr, &sensor_dev_attr_temp2_fault.dev_attr.attr,
&sensor_dev_attr_temp2_beep.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_min.dev_attr.attr,
&sensor_dev_attr_temp3_max.dev_attr.attr, &sensor_dev_attr_temp3_max.dev_attr.attr,
&sensor_dev_attr_temp3_crit.dev_attr.attr, &sensor_dev_attr_temp3_crit.dev_attr.attr,
...@@ -505,7 +640,7 @@ static struct attribute *nct7802_temp_attrs[] = { ...@@ -505,7 +640,7 @@ static struct attribute *nct7802_temp_attrs[] = {
&sensor_dev_attr_temp3_fault.dev_attr.attr, &sensor_dev_attr_temp3_fault.dev_attr.attr,
&sensor_dev_attr_temp3_beep.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_min.dev_attr.attr,
&sensor_dev_attr_temp4_max.dev_attr.attr, &sensor_dev_attr_temp4_max.dev_attr.attr,
&sensor_dev_attr_temp4_crit.dev_attr.attr, &sensor_dev_attr_temp4_crit.dev_attr.attr,
...@@ -514,7 +649,7 @@ static struct attribute *nct7802_temp_attrs[] = { ...@@ -514,7 +649,7 @@ static struct attribute *nct7802_temp_attrs[] = {
&sensor_dev_attr_temp4_crit_alarm.dev_attr.attr, &sensor_dev_attr_temp4_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp4_beep.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_min.dev_attr.attr,
&sensor_dev_attr_temp5_max.dev_attr.attr, &sensor_dev_attr_temp5_max.dev_attr.attr,
&sensor_dev_attr_temp5_crit.dev_attr.attr, &sensor_dev_attr_temp5_crit.dev_attr.attr,
...@@ -523,7 +658,7 @@ static struct attribute *nct7802_temp_attrs[] = { ...@@ -523,7 +658,7 @@ static struct attribute *nct7802_temp_attrs[] = {
&sensor_dev_attr_temp5_crit_alarm.dev_attr.attr, &sensor_dev_attr_temp5_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp5_beep.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, &sensor_dev_attr_temp6_beep.dev_attr.attr,
NULL NULL
...@@ -541,25 +676,27 @@ static umode_t nct7802_temp_is_visible(struct kobject *kobj, ...@@ -541,25 +676,27 @@ static umode_t nct7802_temp_is_visible(struct kobject *kobj,
if (err < 0) if (err < 0)
return 0; return 0;
if (index < 9 && if (index < 10 &&
(reg & 03) != 0x01 && (reg & 0x03) != 0x02) /* RD1 */ (reg & 03) != 0x01 && (reg & 0x03) != 0x02) /* RD1 */
return 0; return 0;
if (index >= 9 && index < 18 &&
if (index >= 10 && index < 20 &&
(reg & 0x0c) != 0x04 && (reg & 0x0c) != 0x08) /* RD2 */ (reg & 0x0c) != 0x04 && (reg & 0x0c) != 0x08) /* RD2 */
return 0; return 0;
if (index >= 18 && index < 27 && (reg & 0x30) != 0x20) /* RD3 */ if (index >= 20 && index < 30 && (reg & 0x30) != 0x20) /* RD3 */
return 0; return 0;
if (index >= 27 && index < 35) /* local */
if (index >= 30 && index < 38) /* local */
return attr->mode; return attr->mode;
err = regmap_read(data->regmap, REG_PECI_ENABLE, &reg); err = regmap_read(data->regmap, REG_PECI_ENABLE, &reg);
if (err < 0) if (err < 0)
return 0; return 0;
if (index >= 35 && index < 43 && !(reg & 0x01)) /* PECI 0 */ if (index >= 38 && index < 46 && !(reg & 0x01)) /* PECI 0 */
return 0; return 0;
if (index >= 0x43 && (!(reg & 0x02))) /* PECI 1 */ if (index >= 0x46 && (!(reg & 0x02))) /* PECI 1 */
return 0; return 0;
return attr->mode; return attr->mode;
...@@ -687,6 +824,27 @@ static SENSOR_DEVICE_ATTR_2(fan3_alarm, S_IRUGO, show_alarm, NULL, 0x1a, 2); ...@@ -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, static SENSOR_DEVICE_ATTR_2(fan3_beep, S_IRUGO | S_IWUSR, show_beep, store_beep,
0x5b, 2); 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[] = { static struct attribute *nct7802_fan_attrs[] = {
&sensor_dev_attr_fan1_input.dev_attr.attr, &sensor_dev_attr_fan1_input.dev_attr.attr,
&sensor_dev_attr_fan1_min.dev_attr.attr, &sensor_dev_attr_fan1_min.dev_attr.attr,
...@@ -725,10 +883,142 @@ static struct attribute_group nct7802_fan_group = { ...@@ -725,10 +883,142 @@ static struct attribute_group nct7802_fan_group = {
.is_visible = nct7802_fan_is_visible, .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[] = { static const struct attribute_group *nct7802_groups[] = {
&nct7802_temp_group, &nct7802_temp_group,
&nct7802_in_group, &nct7802_in_group,
&nct7802_fan_group, &nct7802_fan_group,
&nct7802_pwm_group,
&nct7802_auto_point_group,
NULL NULL
}; };
...@@ -776,7 +1066,8 @@ static int nct7802_detect(struct i2c_client *client, ...@@ -776,7 +1066,8 @@ static int nct7802_detect(struct i2c_client *client,
static bool nct7802_regmap_is_volatile(struct device *dev, unsigned int reg) 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 = { static const struct regmap_config nct7802_regmap_config = {
......
...@@ -20,7 +20,8 @@ config SENSORS_PMBUS ...@@ -20,7 +20,8 @@ config SENSORS_PMBUS
help help
If you say yes here you get hardware monitoring support for generic If you say yes here you get hardware monitoring support for generic
PMBus devices, including but not limited to ADP4000, BMR453, BMR454, 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 This driver can also be built as a module. If so, the module will
be called pmbus. be called pmbus.
...@@ -30,8 +31,8 @@ config SENSORS_ADM1275 ...@@ -30,8 +31,8 @@ config SENSORS_ADM1275
default n default n
help help
If you say yes here you get hardware monitoring support for Analog If you say yes here you get hardware monitoring support for Analog
Devices ADM1075, ADM1275, and ADM1276 Hot-Swap Controller and Digital Devices ADM1075, ADM1275, ADM1276, ADM1293, and ADM1294 Hot-Swap
Power Monitors. Controller and Digital Power Monitors.
This driver can also be built as a module. If so, the module will This driver can also be built as a module. If so, the module will
be called adm1275. be called adm1275.
...@@ -51,7 +52,8 @@ config SENSORS_LTC2978 ...@@ -51,7 +52,8 @@ config SENSORS_LTC2978
default n default n
help help
If you say yes here you get hardware monitoring support for Linear 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 This driver can also be built as a module. If so, the module will
be called ltc2978. be called ltc2978.
...@@ -73,6 +75,16 @@ config SENSORS_MAX16064 ...@@ -73,6 +75,16 @@ config SENSORS_MAX16064
This driver can also be built as a module. If so, the module will This driver can also be built as a module. If so, the module will
be called max16064. 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 config SENSORS_MAX34440
tristate "Maxim MAX34440 and compatibles" tristate "Maxim MAX34440 and compatibles"
default n default n
......
...@@ -8,6 +8,7 @@ obj-$(CONFIG_SENSORS_ADM1275) += adm1275.o ...@@ -8,6 +8,7 @@ obj-$(CONFIG_SENSORS_ADM1275) += adm1275.o
obj-$(CONFIG_SENSORS_LM25066) += lm25066.o obj-$(CONFIG_SENSORS_LM25066) += lm25066.o
obj-$(CONFIG_SENSORS_LTC2978) += ltc2978.o obj-$(CONFIG_SENSORS_LTC2978) += ltc2978.o
obj-$(CONFIG_SENSORS_MAX16064) += max16064.o obj-$(CONFIG_SENSORS_MAX16064) += max16064.o
obj-$(CONFIG_SENSORS_MAX20751) += max20751.o
obj-$(CONFIG_SENSORS_MAX34440) += max34440.o obj-$(CONFIG_SENSORS_MAX34440) += max34440.o
obj-$(CONFIG_SENSORS_MAX8688) += max8688.o obj-$(CONFIG_SENSORS_MAX8688) += max8688.o
obj-$(CONFIG_SENSORS_TPS40422) += tps40422.o obj-$(CONFIG_SENSORS_TPS40422) += tps40422.o
......
...@@ -21,46 +21,120 @@ ...@@ -21,46 +21,120 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/bitops.h>
#include "pmbus.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_IOUT 0xd0
#define ADM1275_PEAK_VIN 0xd1 #define ADM1275_PEAK_VIN 0xd1
#define ADM1275_PEAK_VOUT 0xd2 #define ADM1275_PEAK_VOUT 0xd2
#define ADM1275_PMON_CONFIG 0xd4 #define ADM1275_PMON_CONFIG 0xd4
#define ADM1275_VIN_VOUT_SELECT (1 << 6) #define ADM1275_VIN_VOUT_SELECT BIT(6)
#define ADM1275_VRANGE (1 << 5) #define ADM1275_VRANGE BIT(5)
#define ADM1075_IRANGE_50 (1 << 4) #define ADM1075_IRANGE_50 BIT(4)
#define ADM1075_IRANGE_25 (1 << 3) #define ADM1075_IRANGE_25 BIT(3)
#define ADM1075_IRANGE_MASK ((1 << 3) | (1 << 4)) #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_IOUT_WARN2_LIMIT 0xd7
#define ADM1275_DEVICE_CONFIG 0xd8 #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 ADM1276_PEAK_PIN 0xda
#define ADM1275_MFR_STATUS_IOUT_WARN2 (1 << 0)
#define ADM1075_READ_VAUX 0xdd #define ADM1075_READ_VAUX 0xdd
#define ADM1075_VAUX_OV_WARN_LIMIT 0xde #define ADM1075_VAUX_OV_WARN_LIMIT 0xde
#define ADM1075_VAUX_UV_WARN_LIMIT 0xdf #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_STATUS 0xf6
#define ADM1075_VAUX_OV_WARN (1<<7) #define ADM1075_VAUX_OV_WARN BIT(7)
#define ADM1075_VAUX_UV_WARN (1<<6) #define ADM1075_VAUX_UV_WARN BIT(6)
struct adm1275_data { struct adm1275_data {
int id; int id;
bool have_oc_fault; 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; struct pmbus_driver_info info;
}; };
#define to_adm1275_data(x) container_of(x, struct adm1275_data, 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) 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); 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) ...@@ -72,42 +146,37 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
switch (reg) { switch (reg) {
case PMBUS_IOUT_UC_FAULT_LIMIT: case PMBUS_IOUT_UC_FAULT_LIMIT:
if (data->have_oc_fault) { if (!data->have_uc_fault)
ret = -ENXIO; return -ENXIO;
break;
}
ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT); ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT);
break; break;
case PMBUS_IOUT_OC_FAULT_LIMIT: case PMBUS_IOUT_OC_FAULT_LIMIT:
if (!data->have_oc_fault) { if (!data->have_oc_fault)
ret = -ENXIO; return -ENXIO;
break;
}
ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT); ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT);
break; break;
case PMBUS_VOUT_OV_WARN_LIMIT: case PMBUS_VOUT_OV_WARN_LIMIT:
if (data->id != adm1075) { if (data->have_vout)
ret = -ENODATA; return -ENODATA;
break;
}
ret = pmbus_read_word_data(client, 0, ret = pmbus_read_word_data(client, 0,
ADM1075_VAUX_OV_WARN_LIMIT); ADM1075_VAUX_OV_WARN_LIMIT);
break; break;
case PMBUS_VOUT_UV_WARN_LIMIT: case PMBUS_VOUT_UV_WARN_LIMIT:
if (data->id != adm1075) { if (data->have_vout)
ret = -ENODATA; return -ENODATA;
break;
}
ret = pmbus_read_word_data(client, 0, ret = pmbus_read_word_data(client, 0,
ADM1075_VAUX_UV_WARN_LIMIT); ADM1075_VAUX_UV_WARN_LIMIT);
break; break;
case PMBUS_READ_VOUT: case PMBUS_READ_VOUT:
if (data->id != adm1075) { if (data->have_vout)
ret = -ENODATA; return -ENODATA;
break;
}
ret = pmbus_read_word_data(client, 0, ADM1075_READ_VAUX); ret = pmbus_read_word_data(client, 0, ADM1075_READ_VAUX);
break; 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: case PMBUS_VIRT_READ_IOUT_MAX:
ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_IOUT); ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_IOUT);
break; break;
...@@ -117,11 +186,14 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg) ...@@ -117,11 +186,14 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
case PMBUS_VIRT_READ_VIN_MAX: case PMBUS_VIRT_READ_VIN_MAX:
ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VIN); ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VIN);
break; 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: case PMBUS_VIRT_READ_PIN_MAX:
if (data->id == adm1275) { if (!data->have_pin_max)
ret = -ENXIO; return -ENXIO;
break;
}
ret = pmbus_read_word_data(client, 0, ADM1276_PEAK_PIN); ret = pmbus_read_word_data(client, 0, ADM1276_PEAK_PIN);
break; break;
case PMBUS_VIRT_RESET_IOUT_HISTORY: case PMBUS_VIRT_RESET_IOUT_HISTORY:
...@@ -129,8 +201,8 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg) ...@@ -129,8 +201,8 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
case PMBUS_VIRT_RESET_VIN_HISTORY: case PMBUS_VIRT_RESET_VIN_HISTORY:
break; break;
case PMBUS_VIRT_RESET_PIN_HISTORY: case PMBUS_VIRT_RESET_PIN_HISTORY:
if (data->id == adm1275) if (!data->have_pin_max)
ret = -ENXIO; return -ENXIO;
break; break;
default: default:
ret = -ENODATA; ret = -ENODATA;
...@@ -142,6 +214,8 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg) ...@@ -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, static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
u16 word) u16 word)
{ {
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
const struct adm1275_data *data = to_adm1275_data(info);
int ret; int ret;
if (page) if (page)
...@@ -155,6 +229,9 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg, ...@@ -155,6 +229,9 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
break; break;
case PMBUS_VIRT_RESET_IOUT_HISTORY: case PMBUS_VIRT_RESET_IOUT_HISTORY:
ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_IOUT, 0); 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; break;
case PMBUS_VIRT_RESET_VOUT_HISTORY: case PMBUS_VIRT_RESET_VOUT_HISTORY:
ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VOUT, 0); 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, ...@@ -164,6 +241,9 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
break; break;
case PMBUS_VIRT_RESET_PIN_HISTORY: case PMBUS_VIRT_RESET_PIN_HISTORY:
ret = pmbus_write_word_data(client, 0, ADM1276_PEAK_PIN, 0); 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; break;
default: default:
ret = -ENODATA; ret = -ENODATA;
...@@ -186,29 +266,40 @@ static int adm1275_read_byte_data(struct i2c_client *client, int page, int reg) ...@@ -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); ret = pmbus_read_byte_data(client, page, PMBUS_STATUS_IOUT);
if (ret < 0) if (ret < 0)
break; break;
if (!data->have_oc_fault && !data->have_uc_fault)
break;
mfr_status = pmbus_read_byte_data(client, page, mfr_status = pmbus_read_byte_data(client, page,
PMBUS_STATUS_MFR_SPECIFIC); PMBUS_STATUS_MFR_SPECIFIC);
if (mfr_status < 0) { if (mfr_status < 0)
ret = mfr_status; return mfr_status;
break;
}
if (mfr_status & ADM1275_MFR_STATUS_IOUT_WARN2) { if (mfr_status & ADM1275_MFR_STATUS_IOUT_WARN2) {
ret |= data->have_oc_fault ? ret |= data->have_oc_fault ?
PB_IOUT_OC_FAULT : PB_IOUT_UC_FAULT; PB_IOUT_OC_FAULT : PB_IOUT_UC_FAULT;
} }
break; break;
case PMBUS_STATUS_VOUT: case PMBUS_STATUS_VOUT:
if (data->id != adm1075) { if (data->have_vout)
ret = -ENODATA; return -ENODATA;
break;
}
ret = 0; ret = 0;
mfr_status = pmbus_read_byte_data(client, 0, if (data->have_vaux_status) {
ADM1075_VAUX_STATUS); mfr_status = pmbus_read_byte_data(client, 0,
if (mfr_status & ADM1075_VAUX_OV_WARN) ADM1075_VAUX_STATUS);
ret |= PB_VOLTAGE_OV_WARNING; if (mfr_status < 0)
if (mfr_status & ADM1075_VAUX_UV_WARN) return mfr_status;
ret |= PB_VOLTAGE_UV_WARNING; 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; break;
default: default:
ret = -ENODATA; ret = -ENODATA;
...@@ -221,6 +312,8 @@ static const struct i2c_device_id adm1275_id[] = { ...@@ -221,6 +312,8 @@ static const struct i2c_device_id adm1275_id[] = {
{ "adm1075", adm1075 }, { "adm1075", adm1075 },
{ "adm1275", adm1275 }, { "adm1275", adm1275 },
{ "adm1276", adm1276 }, { "adm1276", adm1276 },
{ "adm1293", adm1293 },
{ "adm1294", adm1294 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, adm1275_id); MODULE_DEVICE_TABLE(i2c, adm1275_id);
...@@ -234,6 +327,8 @@ static int adm1275_probe(struct i2c_client *client, ...@@ -234,6 +327,8 @@ static int adm1275_probe(struct i2c_client *client,
struct pmbus_driver_info *info; struct pmbus_driver_info *info;
struct adm1275_data *data; struct adm1275_data *data;
const struct i2c_device_id *mid; 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, if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_READ_BYTE_DATA I2C_FUNC_SMBUS_READ_BYTE_DATA
...@@ -290,61 +385,38 @@ static int adm1275_probe(struct i2c_client *client, ...@@ -290,61 +385,38 @@ static int adm1275_probe(struct i2c_client *client,
info->format[PSC_VOLTAGE_IN] = direct; info->format[PSC_VOLTAGE_IN] = direct;
info->format[PSC_VOLTAGE_OUT] = direct; info->format[PSC_VOLTAGE_OUT] = direct;
info->format[PSC_CURRENT_OUT] = direct; info->format[PSC_CURRENT_OUT] = direct;
info->m[PSC_CURRENT_OUT] = 807; info->format[PSC_POWER] = direct;
info->b[PSC_CURRENT_OUT] = 20475;
info->R[PSC_CURRENT_OUT] = -1;
info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT; info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
info->read_word_data = adm1275_read_word_data; info->read_word_data = adm1275_read_word_data;
info->read_byte_data = adm1275_read_byte_data; info->read_byte_data = adm1275_read_byte_data;
info->write_word_data = adm1275_write_word_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) { switch (data->id) {
case adm1075: case adm1075:
info->format[PSC_POWER] = direct; if (device_config & ADM1275_IOUT_WARN2_SELECT)
info->b[PSC_POWER] = 0; data->have_oc_fault = true;
info->R[PSC_POWER] = -1; 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) { switch (config & ADM1075_IRANGE_MASK) {
case ADM1075_IRANGE_25: case ADM1075_IRANGE_25:
info->m[PSC_POWER] = 8549; cindex = 1;
info->m[PSC_CURRENT_OUT] = 806; pindex = 3;
break; break;
case ADM1075_IRANGE_50: case ADM1075_IRANGE_50:
info->m[PSC_POWER] = 4279; cindex = 2;
info->m[PSC_CURRENT_OUT] = 404; pindex = 4;
break; break;
default: default:
dev_err(&client->dev, "Invalid input current range"); dev_err(&client->dev, "Invalid input current range");
info->m[PSC_POWER] = 0;
info->m[PSC_CURRENT_OUT] = 0;
break; break;
} }
info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_PIN info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_PIN
| PMBUS_HAVE_STATUS_INPUT; | PMBUS_HAVE_STATUS_INPUT;
if (config & ADM1275_VIN_VOUT_SELECT) if (config & ADM1275_VIN_VOUT_SELECT)
...@@ -352,6 +424,16 @@ static int adm1275_probe(struct i2c_client *client, ...@@ -352,6 +424,16 @@ static int adm1275_probe(struct i2c_client *client,
PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
break; break;
case adm1275: 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) if (config & ADM1275_VIN_VOUT_SELECT)
info->func[0] |= info->func[0] |=
PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
...@@ -360,22 +442,100 @@ static int adm1275_probe(struct i2c_client *client, ...@@ -360,22 +442,100 @@ static int adm1275_probe(struct i2c_client *client,
PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT; PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT;
break; break;
case adm1276: 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 info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_PIN
| PMBUS_HAVE_STATUS_INPUT; | PMBUS_HAVE_STATUS_INPUT;
if (config & ADM1275_VIN_VOUT_SELECT) if (config & ADM1275_VIN_VOUT_SELECT)
info->func[0] |= info->func[0] |=
PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
if (config & ADM1275_VRANGE) { break;
info->m[PSC_POWER] = 6043; case adm1293:
info->b[PSC_POWER] = 0; case adm1294:
info->R[PSC_POWER] = -2; data->have_iout_min = true;
} else { data->have_pin_min = true;
info->m[PSC_POWER] = 2115; data->have_pin_max = true;
info->b[PSC_POWER] = 0; data->have_mfr_vaux_status = true;
info->R[PSC_POWER] = -1;
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; 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); return pmbus_do_probe(client, id, info);
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#include <linux/bitops.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -42,15 +43,15 @@ enum chips { lm25056, lm25063, lm25066, lm5064, lm5066 }; ...@@ -42,15 +43,15 @@ enum chips { lm25056, lm25063, lm25066, lm5064, lm5066 };
#define LM25066_READ_AVG_IIN 0xde #define LM25066_READ_AVG_IIN 0xde
#define LM25066_READ_AVG_PIN 0xdf #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 */ /* LM25056 only */
#define LM25056_VAUX_OV_WARN_LIMIT 0xe3 #define LM25056_VAUX_OV_WARN_LIMIT 0xe3
#define LM25056_VAUX_UV_WARN_LIMIT 0xe4 #define LM25056_VAUX_UV_WARN_LIMIT 0xe4
#define LM25056_MFR_STS_VAUX_OV_WARN (1 << 1) #define LM25056_MFR_STS_VAUX_OV_WARN BIT(1)
#define LM25056_MFR_STS_VAUX_UV_WARN (1 << 0) #define LM25056_MFR_STS_VAUX_UV_WARN BIT(0)
/* LM25063 only */ /* LM25063 only */
......
/* /*
* Hardware monitoring driver for LTC2974, LTC2977, LTC2978, LTC3880, * Hardware monitoring driver for LTC2978 and compatible chips.
* LTC3883, and LTM4676
* *
* Copyright (c) 2011 Ericsson AB. * 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 * 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 * it under the terms of the GNU General Public License as published by
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
* GNU General Public License for more details. * GNU General Public License for more details.
*/ */
#include <linux/delay.h>
#include <linux/jiffies.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -25,49 +27,71 @@ ...@@ -25,49 +27,71 @@
#include <linux/regulator/driver.h> #include <linux/regulator/driver.h>
#include "pmbus.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 */ /* Common for all chips */
#define LTC2978_MFR_VOUT_PEAK 0xdd #define LTC2978_MFR_VOUT_PEAK 0xdd
#define LTC2978_MFR_VIN_PEAK 0xde #define LTC2978_MFR_VIN_PEAK 0xde
#define LTC2978_MFR_TEMPERATURE_PEAK 0xdf #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_VOUT_MIN 0xfb
#define LTC2978_MFR_VIN_MIN 0xfc #define LTC2978_MFR_VIN_MIN 0xfc
#define LTC2978_MFR_TEMPERATURE_MIN 0xfd #define LTC2978_MFR_TEMPERATURE_MIN 0xfd
/* LTC2974 only */ /* LTC2974, LTC2975 */
#define LTC2974_MFR_IOUT_PEAK 0xd7 #define LTC2974_MFR_IOUT_PEAK 0xd7
#define LTC2974_MFR_IOUT_MIN 0xd8 #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_IOUT_PEAK 0xd7
#define LTC3880_MFR_CLEAR_PEAKS 0xe3 #define LTC3880_MFR_CLEAR_PEAKS 0xe3
#define LTC3880_MFR_TEMPERATURE2_PEAK 0xf4 #define LTC3880_MFR_TEMPERATURE2_PEAK 0xf4
/* LTC3883 only */ /* LTC3883 and LTC3886 only */
#define LTC3883_MFR_IIN_PEAK 0xe1 #define LTC3883_MFR_IIN_PEAK 0xe1
#define LTC2974_ID_REV1 0x0212 /* LTC2975 only */
#define LTC2974_ID_REV2 0x0213 #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 LTC2977_ID 0x0130
#define LTC2978_ID_REV1 0x0121 #define LTC2978_ID_REV1 0x0110 /* Early revision */
#define LTC2978_ID_REV2 0x0122 #define LTC2978_ID_REV2 0x0120
#define LTC2978A_ID 0x0124 #define LTC2980_ID_A 0x8030 /* A/B for two die IDs */
#define LTC3880_ID 0x4000 #define LTC2980_ID_B 0x8040
#define LTC3880_ID_MASK 0xff00 #define LTC3880_ID 0x4020
#define LTC3882_ID 0x4200
#define LTC3882_ID_D1 0x4240 /* Dash 1 */
#define LTC3883_ID 0x4300 #define LTC3883_ID 0x4300
#define LTC3883_ID_MASK 0xff00 #define LTC3886_ID 0x4600
#define LTM4676_ID 0x4480 /* datasheet claims 0x440X */ #define LTC3887_ID 0x4700
#define LTM4676_ID_MASK 0xfff0 #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 LTC2974_NUM_PAGES 4
#define LTC2978_NUM_PAGES 8 #define LTC2978_NUM_PAGES 8
#define LTC3880_NUM_PAGES 2 #define LTC3880_NUM_PAGES 2
#define LTC3883_NUM_PAGES 1 #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 * 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 * happens pretty much each time chip data is updated. Raw peak data therefore
...@@ -82,13 +106,91 @@ struct ltc2978_data { ...@@ -82,13 +106,91 @@ struct ltc2978_data {
u16 temp_min[LTC2974_NUM_PAGES], temp_max[LTC2974_NUM_PAGES]; u16 temp_min[LTC2974_NUM_PAGES], temp_max[LTC2974_NUM_PAGES];
u16 vout_min[LTC2978_NUM_PAGES], vout_max[LTC2978_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 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; u16 temp2_max;
struct pmbus_driver_info info; struct pmbus_driver_info info;
u32 features;
}; };
#define to_ltc2978_data(x) container_of(x, struct ltc2978_data, info) #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) static inline int lin11_to_val(int data)
{ {
s16 e = ((s16)data) >> 11; s16 e = ((s16)data) >> 11;
...@@ -102,6 +204,34 @@ static inline int lin11_to_val(int data) ...@@ -102,6 +204,34 @@ static inline int lin11_to_val(int data)
return (e < 0 ? m >> -e : m << e); 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, static int ltc2978_read_word_data_common(struct i2c_client *client, int page,
int reg) int reg)
{ {
...@@ -111,15 +241,11 @@ static int ltc2978_read_word_data_common(struct i2c_client *client, int page, ...@@ -111,15 +241,11 @@ static int ltc2978_read_word_data_common(struct i2c_client *client, int page,
switch (reg) { switch (reg) {
case PMBUS_VIRT_READ_VIN_MAX: case PMBUS_VIRT_READ_VIN_MAX:
ret = pmbus_read_word_data(client, page, LTC2978_MFR_VIN_PEAK); ret = ltc_get_max(data, client, page, LTC2978_MFR_VIN_PEAK,
if (ret >= 0) { &data->vin_max);
if (lin11_to_val(ret) > lin11_to_val(data->vin_max))
data->vin_max = ret;
ret = data->vin_max;
}
break; break;
case PMBUS_VIRT_READ_VOUT_MAX: 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) { if (ret >= 0) {
/* /*
* VOUT is 16 bit unsigned with fixed exponent, * 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, ...@@ -131,14 +257,9 @@ static int ltc2978_read_word_data_common(struct i2c_client *client, int page,
} }
break; break;
case PMBUS_VIRT_READ_TEMP_MAX: case PMBUS_VIRT_READ_TEMP_MAX:
ret = pmbus_read_word_data(client, page, ret = ltc_get_max(data, client, page,
LTC2978_MFR_TEMPERATURE_PEAK); LTC2978_MFR_TEMPERATURE_PEAK,
if (ret >= 0) { &data->temp_max[page]);
if (lin11_to_val(ret)
> lin11_to_val(data->temp_max[page]))
data->temp_max[page] = ret;
ret = data->temp_max[page];
}
break; break;
case PMBUS_VIRT_RESET_VOUT_HISTORY: case PMBUS_VIRT_RESET_VOUT_HISTORY:
case PMBUS_VIRT_RESET_VIN_HISTORY: case PMBUS_VIRT_RESET_VIN_HISTORY:
...@@ -146,6 +267,9 @@ static int ltc2978_read_word_data_common(struct i2c_client *client, int page, ...@@ -146,6 +267,9 @@ static int ltc2978_read_word_data_common(struct i2c_client *client, int page,
ret = 0; ret = 0;
break; break;
default: default:
ret = ltc_wait_ready(client);
if (ret < 0)
return ret;
ret = -ENODATA; ret = -ENODATA;
break; break;
} }
...@@ -160,15 +284,11 @@ static int ltc2978_read_word_data(struct i2c_client *client, int page, int reg) ...@@ -160,15 +284,11 @@ static int ltc2978_read_word_data(struct i2c_client *client, int page, int reg)
switch (reg) { switch (reg) {
case PMBUS_VIRT_READ_VIN_MIN: case PMBUS_VIRT_READ_VIN_MIN:
ret = pmbus_read_word_data(client, page, LTC2978_MFR_VIN_MIN); ret = ltc_get_min(data, client, page, LTC2978_MFR_VIN_MIN,
if (ret >= 0) { &data->vin_min);
if (lin11_to_val(ret) < lin11_to_val(data->vin_min))
data->vin_min = ret;
ret = data->vin_min;
}
break; break;
case PMBUS_VIRT_READ_VOUT_MIN: 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) { if (ret >= 0) {
/* /*
* VOUT_MIN is known to not be supported on some lots * 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) ...@@ -184,14 +304,9 @@ static int ltc2978_read_word_data(struct i2c_client *client, int page, int reg)
} }
break; break;
case PMBUS_VIRT_READ_TEMP_MIN: case PMBUS_VIRT_READ_TEMP_MIN:
ret = pmbus_read_word_data(client, page, ret = ltc_get_min(data, client, page,
LTC2978_MFR_TEMPERATURE_MIN); LTC2978_MFR_TEMPERATURE_MIN,
if (ret >= 0) { &data->temp_min[page]);
if (lin11_to_val(ret)
< lin11_to_val(data->temp_min[page]))
data->temp_min[page] = ret;
ret = data->temp_min[page];
}
break; break;
case PMBUS_VIRT_READ_IOUT_MAX: case PMBUS_VIRT_READ_IOUT_MAX:
case PMBUS_VIRT_RESET_IOUT_HISTORY: case PMBUS_VIRT_RESET_IOUT_HISTORY:
...@@ -214,22 +329,12 @@ static int ltc2974_read_word_data(struct i2c_client *client, int page, int reg) ...@@ -214,22 +329,12 @@ static int ltc2974_read_word_data(struct i2c_client *client, int page, int reg)
switch (reg) { switch (reg) {
case PMBUS_VIRT_READ_IOUT_MAX: case PMBUS_VIRT_READ_IOUT_MAX:
ret = pmbus_read_word_data(client, page, LTC2974_MFR_IOUT_PEAK); ret = ltc_get_max(data, client, page, LTC2974_MFR_IOUT_PEAK,
if (ret >= 0) { &data->iout_max[page]);
if (lin11_to_val(ret)
> lin11_to_val(data->iout_max[page]))
data->iout_max[page] = ret;
ret = data->iout_max[page];
}
break; break;
case PMBUS_VIRT_READ_IOUT_MIN: case PMBUS_VIRT_READ_IOUT_MIN:
ret = pmbus_read_word_data(client, page, LTC2974_MFR_IOUT_MIN); ret = ltc_get_min(data, client, page, LTC2974_MFR_IOUT_MIN,
if (ret >= 0) { &data->iout_min[page]);
if (lin11_to_val(ret)
< lin11_to_val(data->iout_min[page]))
data->iout_min[page] = ret;
ret = data->iout_min[page];
}
break; break;
case PMBUS_VIRT_RESET_IOUT_HISTORY: case PMBUS_VIRT_RESET_IOUT_HISTORY:
ret = 0; ret = 0;
...@@ -241,6 +346,40 @@ static int ltc2974_read_word_data(struct i2c_client *client, int page, int reg) ...@@ -241,6 +346,40 @@ static int ltc2974_read_word_data(struct i2c_client *client, int page, int reg)
return ret; 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) 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); 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) ...@@ -249,22 +388,13 @@ static int ltc3880_read_word_data(struct i2c_client *client, int page, int reg)
switch (reg) { switch (reg) {
case PMBUS_VIRT_READ_IOUT_MAX: case PMBUS_VIRT_READ_IOUT_MAX:
ret = pmbus_read_word_data(client, page, LTC3880_MFR_IOUT_PEAK); ret = ltc_get_max(data, client, page, LTC3880_MFR_IOUT_PEAK,
if (ret >= 0) { &data->iout_max[page]);
if (lin11_to_val(ret)
> lin11_to_val(data->iout_max[page]))
data->iout_max[page] = ret;
ret = data->iout_max[page];
}
break; break;
case PMBUS_VIRT_READ_TEMP2_MAX: case PMBUS_VIRT_READ_TEMP2_MAX:
ret = pmbus_read_word_data(client, page, ret = ltc_get_max(data, client, page,
LTC3880_MFR_TEMPERATURE2_PEAK); LTC3880_MFR_TEMPERATURE2_PEAK,
if (ret >= 0) { &data->temp2_max);
if (lin11_to_val(ret) > lin11_to_val(data->temp2_max))
data->temp2_max = ret;
ret = data->temp2_max;
}
break; break;
case PMBUS_VIRT_READ_VIN_MIN: case PMBUS_VIRT_READ_VIN_MIN:
case PMBUS_VIRT_READ_VOUT_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) ...@@ -290,13 +420,8 @@ static int ltc3883_read_word_data(struct i2c_client *client, int page, int reg)
switch (reg) { switch (reg) {
case PMBUS_VIRT_READ_IIN_MAX: case PMBUS_VIRT_READ_IIN_MAX:
ret = pmbus_read_word_data(client, page, LTC3883_MFR_IIN_PEAK); ret = ltc_get_max(data, client, page, LTC3883_MFR_IIN_PEAK,
if (ret >= 0) { &data->iin_max);
if (lin11_to_val(ret)
> lin11_to_val(data->iin_max))
data->iin_max = ret;
ret = data->iin_max;
}
break; break;
case PMBUS_VIRT_RESET_IIN_HISTORY: case PMBUS_VIRT_RESET_IIN_HISTORY:
ret = 0; ret = 0;
...@@ -308,15 +433,15 @@ static int ltc3883_read_word_data(struct i2c_client *client, int page, int reg) ...@@ -308,15 +433,15 @@ static int ltc3883_read_word_data(struct i2c_client *client, int page, int reg)
return ret; return ret;
} }
static int ltc2978_clear_peaks(struct i2c_client *client, int page, static int ltc2978_clear_peaks(struct ltc2978_data *data,
enum chips id) struct i2c_client *client, int page)
{ {
int ret; int ret;
if (id == ltc3880 || id == ltc3883) if (has_clear_peaks(data))
ret = pmbus_write_byte(client, 0, LTC3880_MFR_CLEAR_PEAKS); ret = ltc_write_byte(client, 0, LTC3880_MFR_CLEAR_PEAKS);
else else
ret = pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS); ret = ltc_write_byte(client, page, PMBUS_CLEAR_FAULTS);
return ret; return ret;
} }
...@@ -331,33 +456,42 @@ static int ltc2978_write_word_data(struct i2c_client *client, int page, ...@@ -331,33 +456,42 @@ static int ltc2978_write_word_data(struct i2c_client *client, int page,
switch (reg) { switch (reg) {
case PMBUS_VIRT_RESET_IIN_HISTORY: case PMBUS_VIRT_RESET_IIN_HISTORY:
data->iin_max = 0x7c00; 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; break;
case PMBUS_VIRT_RESET_IOUT_HISTORY: case PMBUS_VIRT_RESET_IOUT_HISTORY:
data->iout_max[page] = 0x7c00; data->iout_max[page] = 0x7c00;
data->iout_min[page] = 0xfbff; data->iout_min[page] = 0xfbff;
ret = ltc2978_clear_peaks(client, page, data->id); ret = ltc2978_clear_peaks(data, client, page);
break; break;
case PMBUS_VIRT_RESET_TEMP2_HISTORY: case PMBUS_VIRT_RESET_TEMP2_HISTORY:
data->temp2_max = 0x7c00; data->temp2_max = 0x7c00;
ret = ltc2978_clear_peaks(client, page, data->id); ret = ltc2978_clear_peaks(data, client, page);
break; break;
case PMBUS_VIRT_RESET_VOUT_HISTORY: case PMBUS_VIRT_RESET_VOUT_HISTORY:
data->vout_min[page] = 0xffff; data->vout_min[page] = 0xffff;
data->vout_max[page] = 0; data->vout_max[page] = 0;
ret = ltc2978_clear_peaks(client, page, data->id); ret = ltc2978_clear_peaks(data, client, page);
break; break;
case PMBUS_VIRT_RESET_VIN_HISTORY: case PMBUS_VIRT_RESET_VIN_HISTORY:
data->vin_min = 0x7bff; data->vin_min = 0x7bff;
data->vin_max = 0x7c00; data->vin_max = 0x7c00;
ret = ltc2978_clear_peaks(client, page, data->id); ret = ltc2978_clear_peaks(data, client, page);
break; break;
case PMBUS_VIRT_RESET_TEMP_HISTORY: case PMBUS_VIRT_RESET_TEMP_HISTORY:
data->temp_min[page] = 0x7bff; data->temp_min[page] = 0x7bff;
data->temp_max[page] = 0x7c00; data->temp_max[page] = 0x7c00;
ret = ltc2978_clear_peaks(client, page, data->id); ret = ltc2978_clear_peaks(data, client, page);
break; break;
default: default:
ret = ltc_wait_ready(client);
if (ret < 0)
return ret;
ret = -ENODATA; ret = -ENODATA;
break; break;
} }
...@@ -366,10 +500,17 @@ static int ltc2978_write_word_data(struct i2c_client *client, int page, ...@@ -366,10 +500,17 @@ static int ltc2978_write_word_data(struct i2c_client *client, int page,
static const struct i2c_device_id ltc2978_id[] = { static const struct i2c_device_id ltc2978_id[] = {
{"ltc2974", ltc2974}, {"ltc2974", ltc2974},
{"ltc2975", ltc2975},
{"ltc2977", ltc2977}, {"ltc2977", ltc2977},
{"ltc2978", ltc2978}, {"ltc2978", ltc2978},
{"ltc2980", ltc2980},
{"ltc3880", ltc3880}, {"ltc3880", ltc3880},
{"ltc3882", ltc3882},
{"ltc3883", ltc3883}, {"ltc3883", ltc3883},
{"ltc3886", ltc3886},
{"ltc3887", ltc3887},
{"ltm2987", ltm2987},
{"ltm4675", ltm4675},
{"ltm4676", ltm4676}, {"ltm4676", ltm4676},
{} {}
}; };
...@@ -388,10 +529,74 @@ static const struct regulator_desc ltc2978_reg_desc[] = { ...@@ -388,10 +529,74 @@ static const struct regulator_desc ltc2978_reg_desc[] = {
}; };
#endif /* CONFIG_SENSORS_LTC2978_REGULATOR */ #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 = &ltc2978_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, static int ltc2978_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
int chip_id, i; int i, chip_id;
struct ltc2978_data *data; struct ltc2978_data *data;
struct pmbus_driver_info *info; struct pmbus_driver_info *info;
...@@ -404,27 +609,11 @@ static int ltc2978_probe(struct i2c_client *client, ...@@ -404,27 +609,11 @@ static int ltc2978_probe(struct i2c_client *client,
if (!data) if (!data)
return -ENOMEM; return -ENOMEM;
chip_id = i2c_smbus_read_word_data(client, LTC2978_MFR_SPECIAL_ID); chip_id = ltc2978_get_id(client);
if (chip_id < 0) if (chip_id < 0)
return chip_id; return chip_id;
if (chip_id == LTC2974_ID_REV1 || chip_id == LTC2974_ID_REV2) { data->id = chip_id;
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;
}
if (data->id != id->driver_data) if (data->id != id->driver_data)
dev_warn(&client->dev, dev_warn(&client->dev,
"Device mismatch: Configured %s, detected %s\n", "Device mismatch: Configured %s, detected %s\n",
...@@ -433,6 +622,9 @@ static int ltc2978_probe(struct i2c_client *client, ...@@ -433,6 +622,9 @@ static int ltc2978_probe(struct i2c_client *client,
info = &data->info; info = &data->info;
info->write_word_data = ltc2978_write_word_data; 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_min = 0x7bff;
data->vin_max = 0x7c00; data->vin_max = 0x7c00;
...@@ -461,8 +653,23 @@ static int ltc2978_probe(struct i2c_client *client, ...@@ -461,8 +653,23 @@ static int ltc2978_probe(struct i2c_client *client,
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT; | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
} }
break; 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 ltc2977:
case ltc2978: case ltc2978:
case ltc2980:
case ltm2987:
info->read_word_data = ltc2978_read_word_data; info->read_word_data = ltc2978_read_word_data;
info->pages = LTC2978_NUM_PAGES; info->pages = LTC2978_NUM_PAGES;
info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
...@@ -474,7 +681,10 @@ static int ltc2978_probe(struct i2c_client *client, ...@@ -474,7 +681,10 @@ static int ltc2978_probe(struct i2c_client *client,
} }
break; break;
case ltc3880: case ltc3880:
case ltc3887:
case ltm4675:
case ltm4676: case ltm4676:
data->features |= FEAT_CLEAR_PEAKS | FEAT_NEEDS_POLLING;
info->read_word_data = ltc3880_read_word_data; info->read_word_data = ltc3880_read_word_data;
info->pages = LTC3880_NUM_PAGES; info->pages = LTC3880_NUM_PAGES;
info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN
...@@ -488,7 +698,23 @@ static int ltc2978_probe(struct i2c_client *client, ...@@ -488,7 +698,23 @@ static int ltc2978_probe(struct i2c_client *client,
| PMBUS_HAVE_POUT | PMBUS_HAVE_POUT
| PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
break; 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: case ltc3883:
data->features |= FEAT_CLEAR_PEAKS | FEAT_NEEDS_POLLING;
info->read_word_data = ltc3883_read_word_data; info->read_word_data = ltc3883_read_word_data;
info->pages = LTC3883_NUM_PAGES; info->pages = LTC3883_NUM_PAGES;
info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN
...@@ -498,6 +724,21 @@ static int ltc2978_probe(struct i2c_client *client, ...@@ -498,6 +724,21 @@ static int ltc2978_probe(struct i2c_client *client,
| PMBUS_HAVE_PIN | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP | PMBUS_HAVE_PIN | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
| PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP; | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;
break; 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: default:
return -ENODEV; return -ENODEV;
} }
...@@ -517,10 +758,17 @@ static int ltc2978_probe(struct i2c_client *client, ...@@ -517,10 +758,17 @@ static int ltc2978_probe(struct i2c_client *client,
#ifdef CONFIG_OF #ifdef CONFIG_OF
static const struct of_device_id ltc2978_of_match[] = { static const struct of_device_id ltc2978_of_match[] = {
{ .compatible = "lltc,ltc2974" }, { .compatible = "lltc,ltc2974" },
{ .compatible = "lltc,ltc2975" },
{ .compatible = "lltc,ltc2977" }, { .compatible = "lltc,ltc2977" },
{ .compatible = "lltc,ltc2978" }, { .compatible = "lltc,ltc2978" },
{ .compatible = "lltc,ltc2980" },
{ .compatible = "lltc,ltc3880" }, { .compatible = "lltc,ltc3880" },
{ .compatible = "lltc,ltc3882" },
{ .compatible = "lltc,ltc3883" }, { .compatible = "lltc,ltc3883" },
{ .compatible = "lltc,ltc3886" },
{ .compatible = "lltc,ltc3887" },
{ .compatible = "lltc,ltm2987" },
{ .compatible = "lltc,ltm4675" },
{ .compatible = "lltc,ltm4676" }, { .compatible = "lltc,ltm4676" },
{ } { }
}; };
...@@ -540,5 +788,5 @@ static struct i2c_driver ltc2978_driver = { ...@@ -540,5 +788,5 @@ static struct i2c_driver ltc2978_driver = {
module_i2c_driver(ltc2978_driver); module_i2c_driver(ltc2978_driver);
MODULE_AUTHOR("Guenter Roeck"); 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"); MODULE_LICENSE("GPL");
/*
* 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 @@ ...@@ -19,6 +19,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#include <linux/bitops.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -38,10 +39,10 @@ enum chips { max34440, max34441, max34446, max34460, max34461 }; ...@@ -38,10 +39,10 @@ enum chips { max34440, max34441, max34446, max34460, max34461 };
#define MAX34446_MFR_IOUT_AVG 0xe2 #define MAX34446_MFR_IOUT_AVG 0xe2
#define MAX34446_MFR_TEMPERATURE_AVG 0xe3 #define MAX34446_MFR_TEMPERATURE_AVG 0xe3
#define MAX34440_STATUS_OC_WARN (1 << 0) #define MAX34440_STATUS_OC_WARN BIT(0)
#define MAX34440_STATUS_OC_FAULT (1 << 1) #define MAX34440_STATUS_OC_FAULT BIT(1)
#define MAX34440_STATUS_OT_FAULT (1 << 5) #define MAX34440_STATUS_OT_FAULT BIT(5)
#define MAX34440_STATUS_OT_WARN (1 << 6) #define MAX34440_STATUS_OT_WARN BIT(6)
struct max34440_data { struct max34440_data {
int id; int id;
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#include <linux/bitops.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -30,15 +31,15 @@ ...@@ -30,15 +31,15 @@
#define MAX8688_MFR_TEMPERATURE_PEAK 0xd6 #define MAX8688_MFR_TEMPERATURE_PEAK 0xd6
#define MAX8688_MFG_STATUS 0xd8 #define MAX8688_MFG_STATUS 0xd8
#define MAX8688_STATUS_OC_FAULT (1 << 4) #define MAX8688_STATUS_OC_FAULT BIT(4)
#define MAX8688_STATUS_OV_FAULT (1 << 5) #define MAX8688_STATUS_OV_FAULT BIT(5)
#define MAX8688_STATUS_OV_WARNING (1 << 8) #define MAX8688_STATUS_OV_WARNING BIT(8)
#define MAX8688_STATUS_UV_FAULT (1 << 9) #define MAX8688_STATUS_UV_FAULT BIT(9)
#define MAX8688_STATUS_UV_WARNING (1 << 10) #define MAX8688_STATUS_UV_WARNING BIT(10)
#define MAX8688_STATUS_UC_FAULT (1 << 11) #define MAX8688_STATUS_UC_FAULT BIT(11)
#define MAX8688_STATUS_OC_WARNING (1 << 12) #define MAX8688_STATUS_OC_WARNING BIT(12)
#define MAX8688_STATUS_OT_FAULT (1 << 13) #define MAX8688_STATUS_OT_FAULT BIT(13)
#define MAX8688_STATUS_OT_WARNING (1 << 14) #define MAX8688_STATUS_OT_WARNING BIT(14)
static int max8688_read_word_data(struct i2c_client *client, int page, int reg) 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, ...@@ -129,6 +129,7 @@ static int pmbus_identify(struct i2c_client *client,
break; break;
case 1: case 1:
info->format[PSC_VOLTAGE_OUT] = vid; info->format[PSC_VOLTAGE_OUT] = vid;
info->vrm_version = vr11;
break; break;
case 2: case 2:
info->format[PSC_VOLTAGE_OUT] = direct; info->format[PSC_VOLTAGE_OUT] = direct;
...@@ -193,6 +194,10 @@ static const struct i2c_device_id pmbus_id[] = { ...@@ -193,6 +194,10 @@ static const struct i2c_device_id pmbus_id[] = {
{"pdt012", 1}, {"pdt012", 1},
{"pmbus", 0}, {"pmbus", 0},
{"tps40400", 1}, {"tps40400", 1},
{"tps544b20", 1},
{"tps544b25", 1},
{"tps544c20", 1},
{"tps544c25", 1},
{"udt020", 1}, {"udt020", 1},
{} {}
}; };
......
...@@ -19,114 +19,116 @@ ...@@ -19,114 +19,116 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#include <linux/regulator/driver.h>
#ifndef PMBUS_H #ifndef PMBUS_H
#define PMBUS_H #define PMBUS_H
#include <linux/bitops.h>
#include <linux/regulator/driver.h>
/* /*
* Registers * Registers
*/ */
#define PMBUS_PAGE 0x00 enum pmbus_regs {
#define PMBUS_OPERATION 0x01 PMBUS_PAGE = 0x00,
#define PMBUS_ON_OFF_CONFIG 0x02 PMBUS_OPERATION = 0x01,
#define PMBUS_CLEAR_FAULTS 0x03 PMBUS_ON_OFF_CONFIG = 0x02,
#define PMBUS_PHASE 0x04 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 PMBUS_VOUT_MODE = 0x20,
#define PMBUS_VOUT_TRIM 0x22 PMBUS_VOUT_COMMAND = 0x21,
#define PMBUS_VOUT_CAL_OFFSET 0x23 PMBUS_VOUT_TRIM = 0x22,
#define PMBUS_VOUT_MAX 0x24 PMBUS_VOUT_CAL_OFFSET = 0x23,
#define PMBUS_VOUT_MARGIN_HIGH 0x25 PMBUS_VOUT_MAX = 0x24,
#define PMBUS_VOUT_MARGIN_LOW 0x26 PMBUS_VOUT_MARGIN_HIGH = 0x25,
#define PMBUS_VOUT_TRANSITION_RATE 0x27 PMBUS_VOUT_MARGIN_LOW = 0x26,
#define PMBUS_VOUT_DROOP 0x28 PMBUS_VOUT_TRANSITION_RATE = 0x27,
#define PMBUS_VOUT_SCALE_LOOP 0x29 PMBUS_VOUT_DROOP = 0x28,
#define PMBUS_VOUT_SCALE_MONITOR 0x2A 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 PMBUS_FAN_CONFIG_12 = 0x3A,
#define PMBUS_FAN_COMMAND_2 0x3C PMBUS_FAN_COMMAND_1 = 0x3B,
#define PMBUS_FAN_CONFIG_34 0x3D PMBUS_FAN_COMMAND_2 = 0x3C,
#define PMBUS_FAN_COMMAND_3 0x3E PMBUS_FAN_CONFIG_34 = 0x3D,
#define PMBUS_FAN_COMMAND_4 0x3F PMBUS_FAN_COMMAND_3 = 0x3E,
PMBUS_FAN_COMMAND_4 = 0x3F,
#define PMBUS_VOUT_OV_FAULT_LIMIT 0x40
#define PMBUS_VOUT_OV_FAULT_RESPONSE 0x41 PMBUS_VOUT_OV_FAULT_LIMIT = 0x40,
#define PMBUS_VOUT_OV_WARN_LIMIT 0x42 PMBUS_VOUT_OV_FAULT_RESPONSE = 0x41,
#define PMBUS_VOUT_UV_WARN_LIMIT 0x43 PMBUS_VOUT_OV_WARN_LIMIT = 0x42,
#define PMBUS_VOUT_UV_FAULT_LIMIT 0x44 PMBUS_VOUT_UV_WARN_LIMIT = 0x43,
#define PMBUS_VOUT_UV_FAULT_RESPONSE 0x45 PMBUS_VOUT_UV_FAULT_LIMIT = 0x44,
#define PMBUS_IOUT_OC_FAULT_LIMIT 0x46 PMBUS_VOUT_UV_FAULT_RESPONSE = 0x45,
#define PMBUS_IOUT_OC_FAULT_RESPONSE 0x47 PMBUS_IOUT_OC_FAULT_LIMIT = 0x46,
#define PMBUS_IOUT_OC_LV_FAULT_LIMIT 0x48 PMBUS_IOUT_OC_FAULT_RESPONSE = 0x47,
#define PMBUS_IOUT_OC_LV_FAULT_RESPONSE 0x49 PMBUS_IOUT_OC_LV_FAULT_LIMIT = 0x48,
#define PMBUS_IOUT_OC_WARN_LIMIT 0x4A PMBUS_IOUT_OC_LV_FAULT_RESPONSE = 0x49,
#define PMBUS_IOUT_UC_FAULT_LIMIT 0x4B PMBUS_IOUT_OC_WARN_LIMIT = 0x4A,
#define PMBUS_IOUT_UC_FAULT_RESPONSE 0x4C PMBUS_IOUT_UC_FAULT_LIMIT = 0x4B,
PMBUS_IOUT_UC_FAULT_RESPONSE = 0x4C,
#define PMBUS_OT_FAULT_LIMIT 0x4F
#define PMBUS_OT_FAULT_RESPONSE 0x50 PMBUS_OT_FAULT_LIMIT = 0x4F,
#define PMBUS_OT_WARN_LIMIT 0x51 PMBUS_OT_FAULT_RESPONSE = 0x50,
#define PMBUS_UT_WARN_LIMIT 0x52 PMBUS_OT_WARN_LIMIT = 0x51,
#define PMBUS_UT_FAULT_LIMIT 0x53 PMBUS_UT_WARN_LIMIT = 0x52,
#define PMBUS_UT_FAULT_RESPONSE 0x54 PMBUS_UT_FAULT_LIMIT = 0x53,
#define PMBUS_VIN_OV_FAULT_LIMIT 0x55 PMBUS_UT_FAULT_RESPONSE = 0x54,
#define PMBUS_VIN_OV_FAULT_RESPONSE 0x56 PMBUS_VIN_OV_FAULT_LIMIT = 0x55,
#define PMBUS_VIN_OV_WARN_LIMIT 0x57 PMBUS_VIN_OV_FAULT_RESPONSE = 0x56,
#define PMBUS_VIN_UV_WARN_LIMIT 0x58 PMBUS_VIN_OV_WARN_LIMIT = 0x57,
#define PMBUS_VIN_UV_FAULT_LIMIT 0x59 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 PMBUS_POUT_OP_FAULT_LIMIT = 0x68,
#define PMBUS_PIN_OP_WARN_LIMIT 0x6B PMBUS_POUT_OP_WARN_LIMIT = 0x6A,
PMBUS_PIN_OP_WARN_LIMIT = 0x6B,
#define PMBUS_STATUS_BYTE 0x78
#define PMBUS_STATUS_WORD 0x79 PMBUS_STATUS_BYTE = 0x78,
#define PMBUS_STATUS_VOUT 0x7A PMBUS_STATUS_WORD = 0x79,
#define PMBUS_STATUS_IOUT 0x7B PMBUS_STATUS_VOUT = 0x7A,
#define PMBUS_STATUS_INPUT 0x7C PMBUS_STATUS_IOUT = 0x7B,
#define PMBUS_STATUS_TEMPERATURE 0x7D PMBUS_STATUS_INPUT = 0x7C,
#define PMBUS_STATUS_CML 0x7E PMBUS_STATUS_TEMPERATURE = 0x7D,
#define PMBUS_STATUS_OTHER 0x7F PMBUS_STATUS_CML = 0x7E,
#define PMBUS_STATUS_MFR_SPECIFIC 0x80 PMBUS_STATUS_OTHER = 0x7F,
#define PMBUS_STATUS_FAN_12 0x81 PMBUS_STATUS_MFR_SPECIFIC = 0x80,
#define PMBUS_STATUS_FAN_34 0x82 PMBUS_STATUS_FAN_12 = 0x81,
PMBUS_STATUS_FAN_34 = 0x82,
#define PMBUS_READ_VIN 0x88
#define PMBUS_READ_IIN 0x89 PMBUS_READ_VIN = 0x88,
#define PMBUS_READ_VCAP 0x8A PMBUS_READ_IIN = 0x89,
#define PMBUS_READ_VOUT 0x8B PMBUS_READ_VCAP = 0x8A,
#define PMBUS_READ_IOUT 0x8C PMBUS_READ_VOUT = 0x8B,
#define PMBUS_READ_TEMPERATURE_1 0x8D PMBUS_READ_IOUT = 0x8C,
#define PMBUS_READ_TEMPERATURE_2 0x8E PMBUS_READ_TEMPERATURE_1 = 0x8D,
#define PMBUS_READ_TEMPERATURE_3 0x8F PMBUS_READ_TEMPERATURE_2 = 0x8E,
#define PMBUS_READ_FAN_SPEED_1 0x90 PMBUS_READ_TEMPERATURE_3 = 0x8F,
#define PMBUS_READ_FAN_SPEED_2 0x91 PMBUS_READ_FAN_SPEED_1 = 0x90,
#define PMBUS_READ_FAN_SPEED_3 0x92 PMBUS_READ_FAN_SPEED_2 = 0x91,
#define PMBUS_READ_FAN_SPEED_4 0x93 PMBUS_READ_FAN_SPEED_3 = 0x92,
#define PMBUS_READ_DUTY_CYCLE 0x94 PMBUS_READ_FAN_SPEED_4 = 0x93,
#define PMBUS_READ_FREQUENCY 0x95 PMBUS_READ_DUTY_CYCLE = 0x94,
#define PMBUS_READ_POUT 0x96 PMBUS_READ_FREQUENCY = 0x95,
#define PMBUS_READ_PIN 0x97 PMBUS_READ_POUT = 0x96,
PMBUS_READ_PIN = 0x97,
#define PMBUS_REVISION 0x98
#define PMBUS_MFR_ID 0x99 PMBUS_REVISION = 0x98,
#define PMBUS_MFR_MODEL 0x9A PMBUS_MFR_ID = 0x99,
#define PMBUS_MFR_REVISION 0x9B PMBUS_MFR_MODEL = 0x9A,
#define PMBUS_MFR_LOCATION 0x9C PMBUS_MFR_REVISION = 0x9B,
#define PMBUS_MFR_DATE 0x9D PMBUS_MFR_LOCATION = 0x9C,
#define PMBUS_MFR_SERIAL 0x9E PMBUS_MFR_DATE = 0x9D,
PMBUS_MFR_SERIAL = 0x9E,
/* /*
* Virtual registers. * Virtual registers.
...@@ -148,55 +150,58 @@ ...@@ -148,55 +150,58 @@
* the calling PMBus core code will abort if the chip driver returns an error * the calling PMBus core code will abort if the chip driver returns an error
* code when reading or writing virtual registers. * code when reading or writing virtual registers.
*/ */
#define PMBUS_VIRT_BASE 0x100 PMBUS_VIRT_BASE = 0x100,
#define PMBUS_VIRT_READ_TEMP_AVG (PMBUS_VIRT_BASE + 0) PMBUS_VIRT_READ_TEMP_AVG,
#define PMBUS_VIRT_READ_TEMP_MIN (PMBUS_VIRT_BASE + 1) PMBUS_VIRT_READ_TEMP_MIN,
#define PMBUS_VIRT_READ_TEMP_MAX (PMBUS_VIRT_BASE + 2) PMBUS_VIRT_READ_TEMP_MAX,
#define PMBUS_VIRT_RESET_TEMP_HISTORY (PMBUS_VIRT_BASE + 3) PMBUS_VIRT_RESET_TEMP_HISTORY,
#define PMBUS_VIRT_READ_VIN_AVG (PMBUS_VIRT_BASE + 4) PMBUS_VIRT_READ_VIN_AVG,
#define PMBUS_VIRT_READ_VIN_MIN (PMBUS_VIRT_BASE + 5) PMBUS_VIRT_READ_VIN_MIN,
#define PMBUS_VIRT_READ_VIN_MAX (PMBUS_VIRT_BASE + 6) PMBUS_VIRT_READ_VIN_MAX,
#define PMBUS_VIRT_RESET_VIN_HISTORY (PMBUS_VIRT_BASE + 7) PMBUS_VIRT_RESET_VIN_HISTORY,
#define PMBUS_VIRT_READ_IIN_AVG (PMBUS_VIRT_BASE + 8) PMBUS_VIRT_READ_IIN_AVG,
#define PMBUS_VIRT_READ_IIN_MIN (PMBUS_VIRT_BASE + 9) PMBUS_VIRT_READ_IIN_MIN,
#define PMBUS_VIRT_READ_IIN_MAX (PMBUS_VIRT_BASE + 10) PMBUS_VIRT_READ_IIN_MAX,
#define PMBUS_VIRT_RESET_IIN_HISTORY (PMBUS_VIRT_BASE + 11) PMBUS_VIRT_RESET_IIN_HISTORY,
#define PMBUS_VIRT_READ_PIN_AVG (PMBUS_VIRT_BASE + 12) PMBUS_VIRT_READ_PIN_AVG,
#define PMBUS_VIRT_READ_PIN_MAX (PMBUS_VIRT_BASE + 13) PMBUS_VIRT_READ_PIN_MIN,
#define PMBUS_VIRT_RESET_PIN_HISTORY (PMBUS_VIRT_BASE + 14) PMBUS_VIRT_READ_PIN_MAX,
#define PMBUS_VIRT_READ_POUT_AVG (PMBUS_VIRT_BASE + 15) PMBUS_VIRT_RESET_PIN_HISTORY,
#define PMBUS_VIRT_READ_POUT_MAX (PMBUS_VIRT_BASE + 16) PMBUS_VIRT_READ_POUT_AVG,
#define PMBUS_VIRT_RESET_POUT_HISTORY (PMBUS_VIRT_BASE + 17) PMBUS_VIRT_READ_POUT_MIN,
#define PMBUS_VIRT_READ_VOUT_AVG (PMBUS_VIRT_BASE + 18) PMBUS_VIRT_READ_POUT_MAX,
#define PMBUS_VIRT_READ_VOUT_MIN (PMBUS_VIRT_BASE + 19) PMBUS_VIRT_RESET_POUT_HISTORY,
#define PMBUS_VIRT_READ_VOUT_MAX (PMBUS_VIRT_BASE + 20) PMBUS_VIRT_READ_VOUT_AVG,
#define PMBUS_VIRT_RESET_VOUT_HISTORY (PMBUS_VIRT_BASE + 21) PMBUS_VIRT_READ_VOUT_MIN,
#define PMBUS_VIRT_READ_IOUT_AVG (PMBUS_VIRT_BASE + 22) PMBUS_VIRT_READ_VOUT_MAX,
#define PMBUS_VIRT_READ_IOUT_MIN (PMBUS_VIRT_BASE + 23) PMBUS_VIRT_RESET_VOUT_HISTORY,
#define PMBUS_VIRT_READ_IOUT_MAX (PMBUS_VIRT_BASE + 24) PMBUS_VIRT_READ_IOUT_AVG,
#define PMBUS_VIRT_RESET_IOUT_HISTORY (PMBUS_VIRT_BASE + 25) PMBUS_VIRT_READ_IOUT_MIN,
#define PMBUS_VIRT_READ_TEMP2_AVG (PMBUS_VIRT_BASE + 26) PMBUS_VIRT_READ_IOUT_MAX,
#define PMBUS_VIRT_READ_TEMP2_MIN (PMBUS_VIRT_BASE + 27) PMBUS_VIRT_RESET_IOUT_HISTORY,
#define PMBUS_VIRT_READ_TEMP2_MAX (PMBUS_VIRT_BASE + 28) PMBUS_VIRT_READ_TEMP2_AVG,
#define PMBUS_VIRT_RESET_TEMP2_HISTORY (PMBUS_VIRT_BASE + 29) PMBUS_VIRT_READ_TEMP2_MIN,
PMBUS_VIRT_READ_TEMP2_MAX,
#define PMBUS_VIRT_READ_VMON (PMBUS_VIRT_BASE + 30) PMBUS_VIRT_RESET_TEMP2_HISTORY,
#define PMBUS_VIRT_VMON_UV_WARN_LIMIT (PMBUS_VIRT_BASE + 31)
#define PMBUS_VIRT_VMON_OV_WARN_LIMIT (PMBUS_VIRT_BASE + 32) PMBUS_VIRT_READ_VMON,
#define PMBUS_VIRT_VMON_UV_FAULT_LIMIT (PMBUS_VIRT_BASE + 33) PMBUS_VIRT_VMON_UV_WARN_LIMIT,
#define PMBUS_VIRT_VMON_OV_FAULT_LIMIT (PMBUS_VIRT_BASE + 34) PMBUS_VIRT_VMON_OV_WARN_LIMIT,
#define PMBUS_VIRT_STATUS_VMON (PMBUS_VIRT_BASE + 35) PMBUS_VIRT_VMON_UV_FAULT_LIMIT,
PMBUS_VIRT_VMON_OV_FAULT_LIMIT,
PMBUS_VIRT_STATUS_VMON,
};
/* /*
* OPERATION * OPERATION
*/ */
#define PB_OPERATION_CONTROL_ON (1<<7) #define PB_OPERATION_CONTROL_ON BIT(7)
/* /*
* CAPABILITY * CAPABILITY
*/ */
#define PB_CAPABILITY_SMBALERT (1<<4) #define PB_CAPABILITY_SMBALERT BIT(4)
#define PB_CAPABILITY_ERROR_CHECK (1<<7) #define PB_CAPABILITY_ERROR_CHECK BIT(7)
/* /*
* VOUT_MODE * VOUT_MODE
...@@ -211,94 +216,94 @@ ...@@ -211,94 +216,94 @@
/* /*
* Fan configuration * Fan configuration
*/ */
#define PB_FAN_2_PULSE_MASK ((1 << 0) | (1 << 1)) #define PB_FAN_2_PULSE_MASK (BIT(0) | BIT(1))
#define PB_FAN_2_RPM (1 << 2) #define PB_FAN_2_RPM BIT(2)
#define PB_FAN_2_INSTALLED (1 << 3) #define PB_FAN_2_INSTALLED BIT(3)
#define PB_FAN_1_PULSE_MASK ((1 << 4) | (1 << 5)) #define PB_FAN_1_PULSE_MASK (BIT(4) | BIT(5))
#define PB_FAN_1_RPM (1 << 6) #define PB_FAN_1_RPM BIT(6)
#define PB_FAN_1_INSTALLED (1 << 7) #define PB_FAN_1_INSTALLED BIT(7)
/* /*
* STATUS_BYTE, STATUS_WORD (lower) * STATUS_BYTE, STATUS_WORD (lower)
*/ */
#define PB_STATUS_NONE_ABOVE (1<<0) #define PB_STATUS_NONE_ABOVE BIT(0)
#define PB_STATUS_CML (1<<1) #define PB_STATUS_CML BIT(1)
#define PB_STATUS_TEMPERATURE (1<<2) #define PB_STATUS_TEMPERATURE BIT(2)
#define PB_STATUS_VIN_UV (1<<3) #define PB_STATUS_VIN_UV BIT(3)
#define PB_STATUS_IOUT_OC (1<<4) #define PB_STATUS_IOUT_OC BIT(4)
#define PB_STATUS_VOUT_OV (1<<5) #define PB_STATUS_VOUT_OV BIT(5)
#define PB_STATUS_OFF (1<<6) #define PB_STATUS_OFF BIT(6)
#define PB_STATUS_BUSY (1<<7) #define PB_STATUS_BUSY BIT(7)
/* /*
* STATUS_WORD (upper) * STATUS_WORD (upper)
*/ */
#define PB_STATUS_UNKNOWN (1<<8) #define PB_STATUS_UNKNOWN BIT(8)
#define PB_STATUS_OTHER (1<<9) #define PB_STATUS_OTHER BIT(9)
#define PB_STATUS_FANS (1<<10) #define PB_STATUS_FANS BIT(10)
#define PB_STATUS_POWER_GOOD_N (1<<11) #define PB_STATUS_POWER_GOOD_N BIT(11)
#define PB_STATUS_WORD_MFR (1<<12) #define PB_STATUS_WORD_MFR BIT(12)
#define PB_STATUS_INPUT (1<<13) #define PB_STATUS_INPUT BIT(13)
#define PB_STATUS_IOUT_POUT (1<<14) #define PB_STATUS_IOUT_POUT BIT(14)
#define PB_STATUS_VOUT (1<<15) #define PB_STATUS_VOUT BIT(15)
/* /*
* STATUS_IOUT * STATUS_IOUT
*/ */
#define PB_POUT_OP_WARNING (1<<0) #define PB_POUT_OP_WARNING BIT(0)
#define PB_POUT_OP_FAULT (1<<1) #define PB_POUT_OP_FAULT BIT(1)
#define PB_POWER_LIMITING (1<<2) #define PB_POWER_LIMITING BIT(2)
#define PB_CURRENT_SHARE_FAULT (1<<3) #define PB_CURRENT_SHARE_FAULT BIT(3)
#define PB_IOUT_UC_FAULT (1<<4) #define PB_IOUT_UC_FAULT BIT(4)
#define PB_IOUT_OC_WARNING (1<<5) #define PB_IOUT_OC_WARNING BIT(5)
#define PB_IOUT_OC_LV_FAULT (1<<6) #define PB_IOUT_OC_LV_FAULT BIT(6)
#define PB_IOUT_OC_FAULT (1<<7) #define PB_IOUT_OC_FAULT BIT(7)
/* /*
* STATUS_VOUT, STATUS_INPUT * STATUS_VOUT, STATUS_INPUT
*/ */
#define PB_VOLTAGE_UV_FAULT (1<<4) #define PB_VOLTAGE_UV_FAULT BIT(4)
#define PB_VOLTAGE_UV_WARNING (1<<5) #define PB_VOLTAGE_UV_WARNING BIT(5)
#define PB_VOLTAGE_OV_WARNING (1<<6) #define PB_VOLTAGE_OV_WARNING BIT(6)
#define PB_VOLTAGE_OV_FAULT (1<<7) #define PB_VOLTAGE_OV_FAULT BIT(7)
/* /*
* STATUS_INPUT * STATUS_INPUT
*/ */
#define PB_PIN_OP_WARNING (1<<0) #define PB_PIN_OP_WARNING BIT(0)
#define PB_IIN_OC_WARNING (1<<1) #define PB_IIN_OC_WARNING BIT(1)
#define PB_IIN_OC_FAULT (1<<2) #define PB_IIN_OC_FAULT BIT(2)
/* /*
* STATUS_TEMPERATURE * STATUS_TEMPERATURE
*/ */
#define PB_TEMP_UT_FAULT (1<<4) #define PB_TEMP_UT_FAULT BIT(4)
#define PB_TEMP_UT_WARNING (1<<5) #define PB_TEMP_UT_WARNING BIT(5)
#define PB_TEMP_OT_WARNING (1<<6) #define PB_TEMP_OT_WARNING BIT(6)
#define PB_TEMP_OT_FAULT (1<<7) #define PB_TEMP_OT_FAULT BIT(7)
/* /*
* STATUS_FAN * STATUS_FAN
*/ */
#define PB_FAN_AIRFLOW_WARNING (1<<0) #define PB_FAN_AIRFLOW_WARNING BIT(0)
#define PB_FAN_AIRFLOW_FAULT (1<<1) #define PB_FAN_AIRFLOW_FAULT BIT(1)
#define PB_FAN_FAN2_SPEED_OVERRIDE (1<<2) #define PB_FAN_FAN2_SPEED_OVERRIDE BIT(2)
#define PB_FAN_FAN1_SPEED_OVERRIDE (1<<3) #define PB_FAN_FAN1_SPEED_OVERRIDE BIT(3)
#define PB_FAN_FAN2_WARNING (1<<4) #define PB_FAN_FAN2_WARNING BIT(4)
#define PB_FAN_FAN1_WARNING (1<<5) #define PB_FAN_FAN1_WARNING BIT(5)
#define PB_FAN_FAN2_FAULT (1<<6) #define PB_FAN_FAN2_FAULT BIT(6)
#define PB_FAN_FAN1_FAULT (1<<7) #define PB_FAN_FAN1_FAULT BIT(7)
/* /*
* CML_FAULT_STATUS * CML_FAULT_STATUS
*/ */
#define PB_CML_FAULT_OTHER_MEM_LOGIC (1<<0) #define PB_CML_FAULT_OTHER_MEM_LOGIC BIT(0)
#define PB_CML_FAULT_OTHER_COMM (1<<1) #define PB_CML_FAULT_OTHER_COMM BIT(1)
#define PB_CML_FAULT_PROCESSOR (1<<3) #define PB_CML_FAULT_PROCESSOR BIT(3)
#define PB_CML_FAULT_MEMORY (1<<4) #define PB_CML_FAULT_MEMORY BIT(4)
#define PB_CML_FAULT_PACKET_ERROR (1<<5) #define PB_CML_FAULT_PACKET_ERROR BIT(5)
#define PB_CML_FAULT_INVALID_DATA (1<<6) #define PB_CML_FAULT_INVALID_DATA BIT(6)
#define PB_CML_FAULT_INVALID_COMMAND (1<<7) #define PB_CML_FAULT_INVALID_COMMAND BIT(7)
enum pmbus_sensor_classes { enum pmbus_sensor_classes {
PSC_VOLTAGE_IN = 0, PSC_VOLTAGE_IN = 0,
...@@ -314,32 +319,34 @@ enum pmbus_sensor_classes { ...@@ -314,32 +319,34 @@ enum pmbus_sensor_classes {
#define PMBUS_PAGES 32 /* Per PMBus specification */ #define PMBUS_PAGES 32 /* Per PMBus specification */
/* Functionality bit mask */ /* Functionality bit mask */
#define PMBUS_HAVE_VIN (1 << 0) #define PMBUS_HAVE_VIN BIT(0)
#define PMBUS_HAVE_VCAP (1 << 1) #define PMBUS_HAVE_VCAP BIT(1)
#define PMBUS_HAVE_VOUT (1 << 2) #define PMBUS_HAVE_VOUT BIT(2)
#define PMBUS_HAVE_IIN (1 << 3) #define PMBUS_HAVE_IIN BIT(3)
#define PMBUS_HAVE_IOUT (1 << 4) #define PMBUS_HAVE_IOUT BIT(4)
#define PMBUS_HAVE_PIN (1 << 5) #define PMBUS_HAVE_PIN BIT(5)
#define PMBUS_HAVE_POUT (1 << 6) #define PMBUS_HAVE_POUT BIT(6)
#define PMBUS_HAVE_FAN12 (1 << 7) #define PMBUS_HAVE_FAN12 BIT(7)
#define PMBUS_HAVE_FAN34 (1 << 8) #define PMBUS_HAVE_FAN34 BIT(8)
#define PMBUS_HAVE_TEMP (1 << 9) #define PMBUS_HAVE_TEMP BIT(9)
#define PMBUS_HAVE_TEMP2 (1 << 10) #define PMBUS_HAVE_TEMP2 BIT(10)
#define PMBUS_HAVE_TEMP3 (1 << 11) #define PMBUS_HAVE_TEMP3 BIT(11)
#define PMBUS_HAVE_STATUS_VOUT (1 << 12) #define PMBUS_HAVE_STATUS_VOUT BIT(12)
#define PMBUS_HAVE_STATUS_IOUT (1 << 13) #define PMBUS_HAVE_STATUS_IOUT BIT(13)
#define PMBUS_HAVE_STATUS_INPUT (1 << 14) #define PMBUS_HAVE_STATUS_INPUT BIT(14)
#define PMBUS_HAVE_STATUS_TEMP (1 << 15) #define PMBUS_HAVE_STATUS_TEMP BIT(15)
#define PMBUS_HAVE_STATUS_FAN12 (1 << 16) #define PMBUS_HAVE_STATUS_FAN12 BIT(16)
#define PMBUS_HAVE_STATUS_FAN34 (1 << 17) #define PMBUS_HAVE_STATUS_FAN34 BIT(17)
#define PMBUS_HAVE_VMON (1 << 18) #define PMBUS_HAVE_VMON BIT(18)
#define PMBUS_HAVE_STATUS_VMON (1 << 19) #define PMBUS_HAVE_STATUS_VMON BIT(19)
enum pmbus_data_format { linear = 0, direct, vid }; enum pmbus_data_format { linear = 0, direct, vid };
enum vrm_version { vr11 = 0, vr12 };
struct pmbus_driver_info { struct pmbus_driver_info {
int pages; /* Total number of pages */ int pages; /* Total number of pages */
enum pmbus_data_format format[PSC_NUM_CLASSES]; enum pmbus_data_format format[PSC_NUM_CLASSES];
enum vrm_version vrm_version;
/* /*
* Support one set of coefficients for each sensor type * Support one set of coefficients for each sensor type
* Used for chips providing data in direct mode. * Used for chips providing data in direct mode.
...@@ -380,7 +387,7 @@ struct pmbus_driver_info { ...@@ -380,7 +387,7 @@ struct pmbus_driver_info {
/* Regulator ops */ /* 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 */ /* Macro for filling in array of struct regulator_desc */
#define PMBUS_REGULATOR(_name, _id) \ #define PMBUS_REGULATOR(_name, _id) \
...@@ -390,6 +397,7 @@ extern struct regulator_ops pmbus_regulator_ops; ...@@ -390,6 +397,7 @@ extern struct regulator_ops pmbus_regulator_ops;
.of_match = of_match_ptr(_name # _id), \ .of_match = of_match_ptr(_name # _id), \
.regulators_node = of_match_ptr("regulators"), \ .regulators_node = of_match_ptr("regulators"), \
.ops = &pmbus_regulator_ops, \ .ops = &pmbus_regulator_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \ .owner = THIS_MODULE, \
} }
......
...@@ -515,16 +515,24 @@ static long pmbus_reg2data_direct(struct pmbus_data *data, ...@@ -515,16 +515,24 @@ static long pmbus_reg2data_direct(struct pmbus_data *data,
/* /*
* Convert VID sensor values to milli- or micro-units * Convert VID sensor values to milli- or micro-units
* depending on sensor type. * depending on sensor type.
* We currently only support VR11.
*/ */
static long pmbus_reg2data_vid(struct pmbus_data *data, static long pmbus_reg2data_vid(struct pmbus_data *data,
struct pmbus_sensor *sensor) struct pmbus_sensor *sensor)
{ {
long val = sensor->data; long val = sensor->data;
long rv = 0;
if (val < 0x02 || val > 0xb2) switch (data->info->vrm_version) {
return 0; case vr11:
return DIV_ROUND_CLOSEST(160000 - (val - 2) * 625, 100); 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) 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[] = { ...@@ -1328,6 +1336,10 @@ static const struct pmbus_limit_attr pin_limit_attrs[] = {
.reg = PMBUS_VIRT_READ_PIN_AVG, .reg = PMBUS_VIRT_READ_PIN_AVG,
.update = true, .update = true,
.attr = "average", .attr = "average",
}, {
.reg = PMBUS_VIRT_READ_PIN_MIN,
.update = true,
.attr = "input_lowest",
}, { }, {
.reg = PMBUS_VIRT_READ_PIN_MAX, .reg = PMBUS_VIRT_READ_PIN_MAX,
.update = true, .update = true,
...@@ -1358,6 +1370,10 @@ static const struct pmbus_limit_attr pout_limit_attrs[] = { ...@@ -1358,6 +1370,10 @@ static const struct pmbus_limit_attr pout_limit_attrs[] = {
.reg = PMBUS_VIRT_READ_POUT_AVG, .reg = PMBUS_VIRT_READ_POUT_AVG,
.update = true, .update = true,
.attr = "average", .attr = "average",
}, {
.reg = PMBUS_VIRT_READ_POUT_MIN,
.update = true,
.attr = "input_lowest",
}, { }, {
.reg = PMBUS_VIRT_READ_POUT_MAX, .reg = PMBUS_VIRT_READ_POUT_MAX,
.update = true, .update = true,
...@@ -1735,6 +1751,11 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data, ...@@ -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); pmbus_clear_faults(client);
if (info->identify) { if (info->identify) {
...@@ -1796,7 +1817,7 @@ static int pmbus_regulator_disable(struct regulator_dev *rdev) ...@@ -1796,7 +1817,7 @@ static int pmbus_regulator_disable(struct regulator_dev *rdev)
return _pmbus_regulator_on_off(rdev, 0); return _pmbus_regulator_on_off(rdev, 0);
} }
struct regulator_ops pmbus_regulator_ops = { const struct regulator_ops pmbus_regulator_ops = {
.enable = pmbus_regulator_enable, .enable = pmbus_regulator_enable,
.disable = pmbus_regulator_disable, .disable = pmbus_regulator_disable,
.is_enabled = pmbus_regulator_is_enabled, .is_enabled = pmbus_regulator_is_enabled,
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#include <linux/bitops.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -44,16 +45,16 @@ struct zl6100_data { ...@@ -44,16 +45,16 @@ struct zl6100_data {
#define ZL6100_MFR_CONFIG 0xd0 #define ZL6100_MFR_CONFIG 0xd0
#define ZL6100_DEVICE_ID 0xe4 #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_OV_FAULT_LIMIT 0xf5
#define MFR_VMON_UV_FAULT_LIMIT 0xf6 #define MFR_VMON_UV_FAULT_LIMIT 0xf6
#define MFR_READ_VMON 0xf7 #define MFR_READ_VMON 0xf7
#define VMON_UV_WARNING (1 << 5) #define VMON_UV_WARNING BIT(5)
#define VMON_OV_WARNING (1 << 4) #define VMON_OV_WARNING BIT(4)
#define VMON_UV_FAULT (1 << 1) #define VMON_UV_FAULT BIT(1)
#define VMON_OV_FAULT (1 << 0) #define VMON_OV_FAULT BIT(0)
#define ZL6100_WAIT_TIME 1000 /* uS */ #define ZL6100_WAIT_TIME 1000 /* uS */
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/atomic.h> #include <linux/atomic.h>
#include <linux/bitrev.h>
/* Commands */ /* Commands */
#define SHT15_MEASURE_TEMP 0x03 #define SHT15_MEASURE_TEMP 0x03
...@@ -172,19 +173,6 @@ struct sht15_data { ...@@ -172,19 +173,6 @@ struct sht15_data {
atomic_t interrupt_handled; 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 * sht15_crc8() - compute crc8
* @data: sht15 specific data. * @data: sht15 specific data.
...@@ -196,7 +184,7 @@ static u8 sht15_crc8(struct sht15_data *data, ...@@ -196,7 +184,7 @@ static u8 sht15_crc8(struct sht15_data *data,
const u8 *value, const u8 *value,
int len) int len)
{ {
u8 crc = sht15_reverse(data->val_status & 0x0F); u8 crc = bitrev8(data->val_status & 0x0F);
while (len--) { while (len--) {
crc = sht15_crc8_table[*value ^ crc]; crc = sht15_crc8_table[*value ^ crc];
...@@ -477,7 +465,7 @@ static int sht15_update_status(struct sht15_data *data) ...@@ -477,7 +465,7 @@ static int sht15_update_status(struct sht15_data *data)
if (data->checksumming) { if (data->checksumming) {
sht15_ack(data); 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[0] = SHT15_READ_STATUS;
checksum_vals[1] = status; checksum_vals[1] = status;
data->checksum_ok = (sht15_crc8(data, checksum_vals, 2) data->checksum_ok = (sht15_crc8(data, checksum_vals, 2)
...@@ -864,7 +852,7 @@ static void sht15_bh_read_data(struct work_struct *work_s) ...@@ -864,7 +852,7 @@ static void sht15_bh_read_data(struct work_struct *work_s)
*/ */
if (sht15_ack(data)) if (sht15_ack(data))
goto wakeup; 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) ? checksum_vals[0] = (data->state == SHT15_READING_TEMP) ?
SHT15_MEASURE_TEMP : SHT15_MEASURE_RH; SHT15_MEASURE_TEMP : SHT15_MEASURE_RH;
checksum_vals[1] = (u8) (val >> 8); checksum_vals[1] = (u8) (val >> 8);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment