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