Commit 464c9098 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/staging

* 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/staging: (24 commits)
  hwmon: (lm90) Refactor reading of config2 register
  hwmon: (lm90) Make SA56004 detection more robust
  hwmon: (lm90) Simplify handling of extended local temp register
  hwmon: (pmbus) Add client driver for LM25066, LM5064, and LM5066
  hwmon: (max34440) Add support for peak attributes
  hwmon: (max8688) Add support for peak attributes
  hwmon: (max16064) Add support for peak attributes
  hwmon: (adm1275) Add support for peak attributes
  hwmon: (pmbus) Add support for peak attributes
  hwmon: Add new attributes to sysfs ABI
  hwmon: (pmbus) Strengthen check for status register existence
  hwmon: (pmbus) Add support for virtual pages
  hwmon: (pmbus) Support reading and writing of word registers in device specific code
  hwmon: (pmbus) Increase attribute name size
  hwmon: (pmbus) Add ADP4000, NCP4200 and NCP4208 to list of supported devices
  hwmon: (pmbus) Add support for VID output voltage mode
  hwmon: (pmbus) Move PMBus drivers to drivers/hwmon/pmbus
  hwmon: (coretemp) Add core/pkg threshold support to Coretemp
  hwmon: (lm95241) Add support for LM95231
  hwmon: LM95245 driver
  ...
parents 4c677e2e f90be42f
...@@ -43,8 +43,8 @@ Documentation/hwmon/pmbus for details. ...@@ -43,8 +43,8 @@ Documentation/hwmon/pmbus for details.
Sysfs entries Sysfs entries
------------- -------------
The following attributes are supported. Limits are read-write; all other The following attributes are supported. Limits are read-write, history reset
attributes are read-only. attributes are write-only, all other attributes are read-only.
in1_label "vin1" or "vout1" depending on chip variant and in1_label "vin1" or "vout1" depending on chip variant and
configuration. configuration.
...@@ -53,8 +53,12 @@ in1_min Minumum Voltage. From VOUT_UV_WARN_LIMIT register. ...@@ -53,8 +53,12 @@ in1_min Minumum Voltage. From VOUT_UV_WARN_LIMIT register.
in1_max Maximum voltage. From VOUT_OV_WARN_LIMIT register. in1_max Maximum voltage. From VOUT_OV_WARN_LIMIT register.
in1_min_alarm Voltage low alarm. From VOLTAGE_UV_WARNING status. in1_min_alarm Voltage low alarm. From VOLTAGE_UV_WARNING status.
in1_max_alarm Voltage high alarm. From VOLTAGE_OV_WARNING status. in1_max_alarm Voltage high alarm. From VOLTAGE_OV_WARNING status.
in1_highest Historical maximum voltage.
in1_reset_history Write any value to reset history.
curr1_label "iout1" curr1_label "iout1"
curr1_input Measured current. From READ_IOUT register. curr1_input Measured current. From READ_IOUT register.
curr1_max Maximum current. From IOUT_OC_WARN_LIMIT register. curr1_max Maximum current. From IOUT_OC_WARN_LIMIT register.
curr1_max_alarm Current high alarm. From IOUT_OC_WARN_LIMIT register. curr1_max_alarm Current high alarm. From IOUT_OC_WARN_LIMIT register.
curr1_highest Historical maximum current.
curr1_reset_history Write any value to reset history.
...@@ -35,6 +35,13 @@ the Out-Of-Spec bit. Following table summarizes the exported sysfs files: ...@@ -35,6 +35,13 @@ the Out-Of-Spec bit. Following table summarizes the exported sysfs files:
All Sysfs entries are named with their core_id (represented here by 'X'). All Sysfs entries are named with their core_id (represented here by 'X').
tempX_input - Core temperature (in millidegrees Celsius). tempX_input - Core temperature (in millidegrees Celsius).
tempX_max - All cooling devices should be turned on (on Core2). tempX_max - All cooling devices should be turned on (on Core2).
Initialized with IA32_THERM_INTERRUPT. When the CPU
temperature reaches this temperature, an interrupt is
generated and tempX_max_alarm is set.
tempX_max_hyst - If the CPU temperature falls below than temperature,
an interrupt is generated and tempX_max_alarm is reset.
tempX_max_alarm - Set if the temperature reaches or exceeds tempX_max.
Reset if the temperature drops to or below tempX_max_hyst.
tempX_crit - Maximum junction temperature (in millidegrees Celsius). tempX_crit - Maximum junction temperature (in millidegrees Celsius).
tempX_crit_alarm - Set when Out-of-spec bit is set, never clears. tempX_crit_alarm - Set when Out-of-spec bit is set, never clears.
Correct CPU operation is no longer guaranteed. Correct CPU operation is no longer guaranteed.
......
Kernel driver max8688
=====================
Supported chips:
* National Semiconductor LM25066
Prefix: 'lm25066'
Addresses scanned: -
Datasheets:
http://www.national.com/pf/LM/LM25066.html
http://www.national.com/pf/LM/LM25066A.html
* National Semiconductor LM5064
Prefix: 'lm5064'
Addresses scanned: -
Datasheet:
http://www.national.com/pf/LM/LM5064.html
* National Semiconductor LM5066
Prefix: 'lm5066'
Addresses scanned: -
Datasheet:
http://www.national.com/pf/LM/LM5066.html
Author: Guenter Roeck <guenter.roeck@ericsson.com>
Description
-----------
This driver supports hardware montoring for National Semiconductor LM25066,
LM5064, and LM5064 Power Management, Monitoring, Control, and Protection ICs.
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. Limits are read-write; all other
attributes are read-only.
in1_label "vin"
in1_input Measured input voltage.
in1_average Average measured input voltage.
in1_min Minimum input voltage.
in1_max Maximum input voltage.
in1_min_alarm Input voltage low alarm.
in1_max_alarm Input voltage high alarm.
in2_label "vout1"
in2_input Measured output voltage.
in2_average Average measured output voltage.
in2_min Minimum output voltage.
in2_min_alarm Output voltage low alarm.
in3_label "vout2"
in3_input Measured voltage on vaux pin
curr1_label "iin"
curr1_input Measured input current.
curr1_average Average measured input current.
curr1_max Maximum input current.
curr1_max_alarm Input current high alarm.
power1_label "pin"
power1_input Measured input power.
power1_average Average measured input power.
power1_max Maximum input power limit.
power1_alarm Input power alarm
power1_input_highest Historical maximum power.
power1_reset_history Write any value to reset maximum power history.
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.
...@@ -113,7 +113,11 @@ Supported chips: ...@@ -113,7 +113,11 @@ Supported chips:
Prefix: 'w83l771' Prefix: 'w83l771'
Addresses scanned: I2C 0x4c Addresses scanned: I2C 0x4c
Datasheet: Not publicly available, can be requested from Nuvoton Datasheet: Not publicly available, can be requested from Nuvoton
* Philips/NXP SA56004X
Prefix: 'sa56004'
Addresses scanned: I2C 0x48 through 0x4F
Datasheet: Publicly available at NXP website
http://ics.nxp.com/products/interface/datasheet/sa56004x.pdf
Author: Jean Delvare <khali@linux-fr.org> Author: Jean Delvare <khali@linux-fr.org>
...@@ -193,6 +197,9 @@ W83L771AWG/ASG ...@@ -193,6 +197,9 @@ W83L771AWG/ASG
* The AWG and ASG variants only differ in package format. * The AWG and ASG variants only differ in package format.
* Diode ideality factor configuration (remote sensor) at 0xE3 * Diode ideality factor configuration (remote sensor) at 0xE3
SA56004X:
* Better local resolution
All temperature values are given in degrees Celsius. Resolution All temperature values are given in degrees Celsius. Resolution
is 1.0 degree for the local temperature, 0.125 degree for the remote is 1.0 degree for the local temperature, 0.125 degree for the remote
temperature, except for the MAX6657, MAX6658 and MAX6659 which have a temperature, except for the MAX6657, MAX6658 and MAX6659 which have a
......
Kernel driver lm95245
==================
Supported chips:
* National Semiconductor LM95245
Addresses scanned: I2C 0x18, 0x19, 0x29, 0x4c, 0x4d
Datasheet: Publicly available at the National Semiconductor website
http://www.national.com/mpf/LM/LM95245.html
Author: Alexander Stein <alexander.stein@systec-electronic.com>
Description
-----------
The LM95245 is an 11-bit digital temperature sensor with a 2-wire System
Management Bus (SMBus) interface and TruTherm technology that can monitor
the temperature of a remote diode as well as its own temperature.
The LM95245 can be used to very accurately monitor the temperature of
external devices such as microprocessors.
All temperature values are given in millidegrees Celsius. Local temperature
is given within a range of -127 to +127.875 degrees. Remote temperatures are
given within a range of -127 to +255 degrees. Resolution depends on
temperature input and range.
Each sensor has its own critical limit, but the hysteresis is common to all
two channels.
The lm95245 driver can change its update interval to a fixed set of values.
It will round up to the next selectable interval. See the datasheet for exact
values. Reading sensor values more often will do no harm, but will return
'old' values.
...@@ -50,6 +50,8 @@ in[1-4]_min_alarm Voltage low alarm. From VOLTAGE_UV_WARNING status. ...@@ -50,6 +50,8 @@ in[1-4]_min_alarm Voltage low alarm. From VOLTAGE_UV_WARNING status.
in[1-4]_max_alarm Voltage high alarm. From VOLTAGE_OV_WARNING status. in[1-4]_max_alarm Voltage high alarm. From VOLTAGE_OV_WARNING status.
in[1-4]_lcrit_alarm Voltage critical low alarm. From VOLTAGE_UV_FAULT status. in[1-4]_lcrit_alarm Voltage critical low alarm. From VOLTAGE_UV_FAULT status.
in[1-4]_crit_alarm Voltage critical high alarm. From VOLTAGE_OV_FAULT status. in[1-4]_crit_alarm Voltage critical high alarm. From VOLTAGE_OV_FAULT status.
in[1-4]_highest Historical maximum voltage.
in[1-4]_reset_history Write any value to reset history.
temp1_input Measured temperature. From READ_TEMPERATURE_1 register. temp1_input Measured temperature. From READ_TEMPERATURE_1 register.
temp1_max Maximum temperature. From OT_WARN_LIMIT register. temp1_max Maximum temperature. From OT_WARN_LIMIT register.
...@@ -60,3 +62,5 @@ temp1_max_alarm Chip temperature high alarm. Set by comparing ...@@ -60,3 +62,5 @@ temp1_max_alarm Chip temperature high alarm. Set by comparing
temp1_crit_alarm Chip temperature critical high alarm. Set by comparing temp1_crit_alarm Chip temperature critical high alarm. Set by comparing
READ_TEMPERATURE_1 with OT_FAULT_LIMIT if TEMP_OT_FAULT READ_TEMPERATURE_1 with OT_FAULT_LIMIT if TEMP_OT_FAULT
status is set. status is set.
temp1_highest Historical maximum temperature.
temp1_reset_history Write any value to reset history.
Kernel driver max1668
=====================
Supported chips:
* Maxim MAX1668, MAX1805 and MAX1989
Prefix: 'max1668'
Addresses scanned: I2C 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e
Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX1668-MAX1989.pdf
Author:
David George <david.george@ska.ac.za>
Description
-----------
This driver implements support for the Maxim MAX1668, MAX1805 and MAX1989
chips.
The three devices are very similar, but the MAX1805 has a reduced feature
set; only two remote temperature inputs vs the four avaible on the other
two ICs.
The driver is able to distinguish between the devices and creates sysfs
entries as follows:
MAX1805, MAX1668 and MAX1989:
temp1_input ro local (ambient) temperature
temp1_max rw local temperature maximum threshold for alarm
temp1_max_alarm ro local temperature maximum threshold alarm
temp1_min rw local temperature minimum threshold for alarm
temp1_min_alarm ro local temperature minimum threshold alarm
temp2_input ro remote temperature 1
temp2_max rw remote temperature 1 maximum threshold for alarm
temp2_max_alarm ro remote temperature 1 maximum threshold alarm
temp2_min rw remote temperature 1 minimum threshold for alarm
temp2_min_alarm ro remote temperature 1 minimum threshold alarm
temp3_input ro remote temperature 2
temp3_max rw remote temperature 2 maximum threshold for alarm
temp3_max_alarm ro remote temperature 2 maximum threshold alarm
temp3_min rw remote temperature 2 minimum threshold for alarm
temp3_min_alarm ro remote temperature 2 minimum threshold alarm
MAX1668 and MAX1989 only:
temp4_input ro remote temperature 3
temp4_max rw remote temperature 3 maximum threshold for alarm
temp4_max_alarm ro remote temperature 3 maximum threshold alarm
temp4_min rw remote temperature 3 minimum threshold for alarm
temp4_min_alarm ro remote temperature 3 minimum threshold alarm
temp5_input ro remote temperature 4
temp5_max rw remote temperature 4 maximum threshold for alarm
temp5_max_alarm ro remote temperature 4 maximum threshold alarm
temp5_min rw remote temperature 4 minimum threshold for alarm
temp5_min_alarm ro remote temperature 4 minimum threshold alarm
Module Parameters
-----------------
* read_only: int
Set to non-zero if you wish to prevent write access to alarm thresholds.
...@@ -56,6 +56,8 @@ in[1-6]_min_alarm Voltage low alarm. From VOLTAGE_UV_WARNING status. ...@@ -56,6 +56,8 @@ in[1-6]_min_alarm Voltage low alarm. From VOLTAGE_UV_WARNING status.
in[1-6]_max_alarm Voltage high alarm. From VOLTAGE_OV_WARNING status. in[1-6]_max_alarm Voltage high alarm. From VOLTAGE_OV_WARNING status.
in[1-6]_lcrit_alarm Voltage critical low alarm. From VOLTAGE_UV_FAULT status. in[1-6]_lcrit_alarm Voltage critical low alarm. From VOLTAGE_UV_FAULT status.
in[1-6]_crit_alarm Voltage critical high alarm. From VOLTAGE_OV_FAULT status. in[1-6]_crit_alarm Voltage critical high alarm. From VOLTAGE_OV_FAULT status.
in[1-6]_highest Historical maximum voltage.
in[1-6]_reset_history Write any value to reset history.
curr[1-6]_label "iout[1-6]". curr[1-6]_label "iout[1-6]".
curr[1-6]_input Measured current. From READ_IOUT register. curr[1-6]_input Measured current. From READ_IOUT register.
...@@ -63,6 +65,8 @@ curr[1-6]_max Maximum current. From IOUT_OC_WARN_LIMIT register. ...@@ -63,6 +65,8 @@ curr[1-6]_max Maximum current. From IOUT_OC_WARN_LIMIT register.
curr[1-6]_crit Critical maximum current. From IOUT_OC_FAULT_LIMIT register. curr[1-6]_crit Critical maximum current. From IOUT_OC_FAULT_LIMIT register.
curr[1-6]_max_alarm Current high alarm. From IOUT_OC_WARNING status. curr[1-6]_max_alarm Current high alarm. From IOUT_OC_WARNING status.
curr[1-6]_crit_alarm Current critical high alarm. From IOUT_OC_FAULT status. curr[1-6]_crit_alarm Current critical high alarm. From IOUT_OC_FAULT status.
curr[1-6]_highest Historical maximum current.
curr[1-6]_reset_history Write any value to reset history.
in6 and curr6 attributes only exist for MAX34440. in6 and curr6 attributes only exist for MAX34440.
...@@ -75,5 +79,7 @@ temp[1-8]_max Maximum temperature. From OT_WARN_LIMIT register. ...@@ -75,5 +79,7 @@ temp[1-8]_max Maximum temperature. From OT_WARN_LIMIT register.
temp[1-8]_crit Critical high temperature. From OT_FAULT_LIMIT register. temp[1-8]_crit Critical high temperature. From OT_FAULT_LIMIT register.
temp[1-8]_max_alarm Temperature high alarm. temp[1-8]_max_alarm Temperature high alarm.
temp[1-8]_crit_alarm Temperature critical high alarm. temp[1-8]_crit_alarm Temperature critical high alarm.
temp[1-8]_highest Historical maximum temperature.
temp[1-8]_reset_history Write any value to reset history.
temp7 and temp8 attributes only exist for MAX34440. temp7 and temp8 attributes only exist for MAX34440.
...@@ -50,6 +50,8 @@ in1_min_alarm Voltage low alarm. From VOLTAGE_UV_WARNING status. ...@@ -50,6 +50,8 @@ in1_min_alarm Voltage low alarm. From VOLTAGE_UV_WARNING status.
in1_max_alarm Voltage high alarm. From VOLTAGE_OV_WARNING status. in1_max_alarm Voltage high alarm. From VOLTAGE_OV_WARNING status.
in1_lcrit_alarm Voltage critical low alarm. From VOLTAGE_UV_FAULT status. in1_lcrit_alarm Voltage critical low alarm. From VOLTAGE_UV_FAULT status.
in1_crit_alarm Voltage critical high alarm. From VOLTAGE_OV_FAULT status. in1_crit_alarm Voltage critical high alarm. From VOLTAGE_OV_FAULT status.
in1_highest Historical maximum voltage.
in1_reset_history Write any value to reset history.
curr1_label "iout1" curr1_label "iout1"
curr1_input Measured current. From READ_IOUT register. curr1_input Measured current. From READ_IOUT register.
...@@ -57,6 +59,8 @@ curr1_max Maximum current. From IOUT_OC_WARN_LIMIT register. ...@@ -57,6 +59,8 @@ curr1_max Maximum current. From IOUT_OC_WARN_LIMIT register.
curr1_crit Critical maximum current. From IOUT_OC_FAULT_LIMIT register. curr1_crit Critical maximum current. From IOUT_OC_FAULT_LIMIT register.
curr1_max_alarm Current high alarm. From IOUT_OC_WARN_LIMIT register. curr1_max_alarm Current high alarm. From IOUT_OC_WARN_LIMIT register.
curr1_crit_alarm Current critical high alarm. From IOUT_OC_FAULT status. curr1_crit_alarm Current critical high alarm. From IOUT_OC_FAULT status.
curr1_highest Historical maximum current.
curr1_reset_history Write any value to reset history.
temp1_input Measured temperature. From READ_TEMPERATURE_1 register. temp1_input Measured temperature. From READ_TEMPERATURE_1 register.
temp1_max Maximum temperature. From OT_WARN_LIMIT register. temp1_max Maximum temperature. From OT_WARN_LIMIT register.
...@@ -67,3 +71,5 @@ temp1_max_alarm Chip temperature high alarm. Set by comparing ...@@ -67,3 +71,5 @@ temp1_max_alarm Chip temperature high alarm. Set by comparing
temp1_crit_alarm Chip temperature critical high alarm. Set by comparing temp1_crit_alarm Chip temperature critical high alarm. Set by comparing
READ_TEMPERATURE_1 with OT_FAULT_LIMIT if TEMP_OT_FAULT READ_TEMPERATURE_1 with OT_FAULT_LIMIT if TEMP_OT_FAULT
status is set. status is set.
temp1_highest Historical maximum temperature.
temp1_reset_history Write any value to reset history.
Kernel driver ntc_thermistor
=================
Supported thermistors:
* Murata NTC Thermistors NCP15WB473, NCP18WB473, NCP21WB473, NCP03WB473, NCP15WL333
Prefixes: 'ncp15wb473', 'ncp18wb473', 'ncp21wb473', 'ncp03wb473', 'ncp15wl333'
Datasheet: Publicly available at Murata
Other NTC thermistors can be supported simply by adding compensation
tables; e.g., NCP15WL333 support is added by the table ncpXXwl333.
Authors:
MyungJoo Ham <myungjoo.ham@samsung.com>
Description
-----------
The NTC thermistor is a simple thermistor that requires users to provide the
resistance and lookup the corresponding compensation table to get the
temperature input.
The NTC driver provides lookup tables with a linear approximation function
and four circuit models with an option not to use any of the four models.
The four circuit models provided are:
$: resister, [TH]: the thermistor
1. connect = NTC_CONNECTED_POSITIVE, pullup_ohm > 0
[pullup_uV]
| |
[TH] $ (pullup_ohm)
| |
+----+-----------------------[read_uV]
|
$ (pulldown_ohm)
|
--- (ground)
2. connect = NTC_CONNECTED_POSITIVE, pullup_ohm = 0 (not-connected)
[pullup_uV]
|
[TH]
|
+----------------------------[read_uV]
|
$ (pulldown_ohm)
|
--- (ground)
3. connect = NTC_CONNECTED_GROUND, pulldown_ohm > 0
[pullup_uV]
|
$ (pullup_ohm)
|
+----+-----------------------[read_uV]
| |
[TH] $ (pulldown_ohm)
| |
-------- (ground)
4. connect = NTC_CONNECTED_GROUND, pulldown_ohm = 0 (not-connected)
[pullup_uV]
|
$ (pullup_ohm)
|
+----------------------------[read_uV]
|
[TH]
|
--- (ground)
When one of the four circuit models is used, read_uV, pullup_uV, pullup_ohm,
pulldown_ohm, and connect should be provided. When none of the four models
are suitable or the user can get the resistance directly, the user should
provide read_ohm and _not_ provide the others.
Sysfs Interface
---------------
name the mandatory global attribute, the thermistor name.
temp1_type always 4 (thermistor)
RO
temp1_input measure the temperature and provide the measured value.
(reading this file initiates the reading procedure.)
RO
Note that each NTC thermistor has only _one_ thermistor; thus, only temp1 exists.
...@@ -13,6 +13,13 @@ Supported chips: ...@@ -13,6 +13,13 @@ Supported chips:
Prefix: 'ltc2978' Prefix: 'ltc2978'
Addresses scanned: - Addresses scanned: -
Datasheet: http://cds.linear.com/docs/Datasheet/2978fa.pdf Datasheet: http://cds.linear.com/docs/Datasheet/2978fa.pdf
* ON Semiconductor ADP4000, NCP4200, NCP4208
Prefixes: 'adp4000', 'ncp4200', 'ncp4208'
Addresses scanned: -
Datasheets:
http://www.onsemi.com/pub_link/Collateral/ADP4000-D.PDF
http://www.onsemi.com/pub_link/Collateral/NCP4200-D.PDF
http://www.onsemi.com/pub_link/Collateral/JUNE%202009-%20REV.%200.PDF
* Generic PMBus devices * Generic PMBus devices
Prefix: 'pmbus' Prefix: 'pmbus'
Addresses scanned: - Addresses scanned: -
......
...@@ -139,6 +139,29 @@ in[0-*]_input Voltage input value. ...@@ -139,6 +139,29 @@ in[0-*]_input Voltage input value.
thumb: drivers should report the voltage values at the thumb: drivers should report the voltage values at the
"pins" of the chip. "pins" of the chip.
in[0-*]_average
Average voltage
Unit: millivolt
RO
in[0-*]_lowest
Historical minimum voltage
Unit: millivolt
RO
in[0-*]_highest
Historical maximum voltage
Unit: millivolt
RO
in[0-*]_reset_history
Reset inX_lowest and inX_highest
WO
in_reset_history
Reset inX_lowest and inX_highest for all sensors
WO
in[0-*]_label Suggested voltage channel label. in[0-*]_label Suggested voltage channel label.
Text string Text string
Should only be created if the driver has hints about what Should only be created if the driver has hints about what
...@@ -407,6 +430,29 @@ curr[1-*]_input Current input value ...@@ -407,6 +430,29 @@ curr[1-*]_input Current input value
Unit: milliampere Unit: milliampere
RO RO
curr[1-*]_average
Average current use
Unit: milliampere
RO
curr[1-*]_lowest
Historical minimum current
Unit: milliampere
RO
curr[1-*]_highest
Historical maximum current
Unit: milliampere
RO
curr[1-*]_reset_history
Reset currX_lowest and currX_highest
WO
curr_reset_history
Reset currX_lowest and currX_highest for all sensors
WO
Also see the Alarms section for status flags associated with currents. Also see the Alarms section for status flags associated with currents.
********* *********
......
...@@ -4150,6 +4150,13 @@ S: Orphan ...@@ -4150,6 +4150,13 @@ S: Orphan
F: drivers/video/matrox/matroxfb_* F: drivers/video/matrox/matroxfb_*
F: include/linux/matroxfb.h F: include/linux/matroxfb.h
MAX1668 TEMPERATURE SENSOR DRIVER
M: "David George" <david.george@ska.ac.za>
L: lm-sensors@lm-sensors.org
S: Maintained
F: Documentation/hwmon/max1668
F: drivers/hwmon/max1668.c
MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER
M: "Hans J. Koch" <hjk@hansjkoch.de> M: "Hans J. Koch" <hjk@hansjkoch.de>
L: lm-sensors@lm-sensors.org L: lm-sensors@lm-sensors.org
...@@ -4999,6 +5006,17 @@ F: drivers/i2c/busses/i2c-puv3.c ...@@ -4999,6 +5006,17 @@ F: drivers/i2c/busses/i2c-puv3.c
F: drivers/video/fb-puv3.c F: drivers/video/fb-puv3.c
F: drivers/rtc/rtc-puv3.c F: drivers/rtc/rtc-puv3.c
PMBUS HARDWARE MONITORING DRIVERS
M: Guenter Roeck <guenter.roeck@ericsson.com>
L: lm-sensors@lm-sensors.org
W: http://www.lm-sensors.org/
W: http://www.roeck-us.net/linux/drivers/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
S: Maintained
F: Documentation/hwmon/pmbus
F: drivers/hwmon/pmbus/
F: include/linux/i2c/pmbus.h
PMC SIERRA MaxRAID DRIVER PMC SIERRA MaxRAID DRIVER
M: Anil Ravindranath <anil_ravindranath@pmc-sierra.com> M: Anil Ravindranath <anil_ravindranath@pmc-sierra.com>
L: linux-scsi@vger.kernel.org L: linux-scsi@vger.kernel.org
......
...@@ -623,7 +623,7 @@ config SENSORS_LM90 ...@@ -623,7 +623,7 @@ config SENSORS_LM90
LM86, LM89 and LM99, Analog Devices ADM1032, ADT7461, and ADT7461A, LM86, LM89 and LM99, Analog Devices ADM1032, ADT7461, and ADT7461A,
Maxim MAX6646, MAX6647, MAX6648, MAX6649, MAX6657, MAX6658, MAX6659, Maxim MAX6646, MAX6647, MAX6648, MAX6649, MAX6657, MAX6658, MAX6659,
MAX6680, MAX6681, MAX6692, MAX6695, MAX6696, ON Semiconductor NCT1008, MAX6680, MAX6681, MAX6692, MAX6695, MAX6696, ON Semiconductor NCT1008,
and Winbond/Nuvoton W83L771W/G/AWG/ASG sensor chips. Winbond/Nuvoton W83L771W/G/AWG/ASG and Philips SA56004 sensor chips.
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called lm90. will be called lm90.
...@@ -694,14 +694,24 @@ config SENSORS_LTC4261 ...@@ -694,14 +694,24 @@ config SENSORS_LTC4261
be called ltc4261. be called ltc4261.
config SENSORS_LM95241 config SENSORS_LM95241
tristate "National Semiconductor LM95241 sensor chip" tristate "National Semiconductor LM95241 and compatibles"
depends on I2C depends on I2C
help help
If you say yes here you get support for LM95241 sensor chip. If you say yes here you get support for LM95231 and LM95241 sensor
chips.
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called lm95241. will be called lm95241.
config SENSORS_LM95245
tristate "National Semiconductor LM95245 sensor chip"
depends on I2C && EXPERIMENTAL
help
If you say yes here you get support for LM95245 sensor chip.
This driver can also be built as a module. If so, the module
will be called lm95245.
config SENSORS_MAX1111 config SENSORS_MAX1111
tristate "Maxim MAX1111 Multichannel, Serial 8-bit ADC chip" tristate "Maxim MAX1111 Multichannel, Serial 8-bit ADC chip"
depends on SPI_MASTER depends on SPI_MASTER
...@@ -736,6 +746,16 @@ config SENSORS_MAX1619 ...@@ -736,6 +746,16 @@ config SENSORS_MAX1619
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called max1619. will be called max1619.
config SENSORS_MAX1668
tristate "Maxim MAX1668 and compatibles"
depends on I2C && EXPERIMENTAL
help
If you say yes here you get support for MAX1668, MAX1989 and
MAX1805 chips.
This driver can also be built as a module. If so, the module
will be called max1668.
config SENSORS_MAX6639 config SENSORS_MAX6639
tristate "Maxim MAX6639 sensor chip" tristate "Maxim MAX6639 sensor chip"
depends on I2C && EXPERIMENTAL depends on I2C && EXPERIMENTAL
...@@ -767,6 +787,20 @@ config SENSORS_MAX6650 ...@@ -767,6 +787,20 @@ config SENSORS_MAX6650
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called max6650. will be called max6650.
config SENSORS_NTC_THERMISTOR
tristate "NTC thermistor support"
depends on EXPERIMENTAL
help
This driver supports NTC thermistors sensor reading and its
interpretation. The driver can also monitor the temperature and
send notifications about the temperature.
Currently, this driver supports
NCP15WB473, NCP18WB473, NCP21WB473, NCP03WB473, and NCP15WL333.
This driver can also be built as a module. If so, the module
will be called ntc-thermistor.
config SENSORS_PC87360 config SENSORS_PC87360
tristate "National Semiconductor PC87360 family" tristate "National Semiconductor PC87360 family"
select HWMON_VID select HWMON_VID
...@@ -807,92 +841,7 @@ config SENSORS_PCF8591 ...@@ -807,92 +841,7 @@ config SENSORS_PCF8591
These devices are hard to detect and rarely found on mainstream These devices are hard to detect and rarely found on mainstream
hardware. If unsure, say N. hardware. If unsure, say N.
config PMBUS source drivers/hwmon/pmbus/Kconfig
tristate "PMBus support"
depends on I2C && EXPERIMENTAL
default n
help
Say yes here if you want to enable PMBus support.
This driver can also be built as a module. If so, the module will
be called pmbus_core.
if PMBUS
config SENSORS_PMBUS
tristate "Generic PMBus devices"
default n
help
If you say yes here you get hardware monitoring support for generic
PMBus devices, including but not limited to BMR450, BMR451, BMR453,
BMR454, and LTC2978.
This driver can also be built as a module. If so, the module will
be called pmbus.
config SENSORS_ADM1275
tristate "Analog Devices ADM1275"
default n
help
If you say yes here you get hardware monitoring support for Analog
Devices ADM1275 Hot-Swap Controller and Digital Power Monitor.
This driver can also be built as a module. If so, the module will
be called adm1275.
config SENSORS_MAX16064
tristate "Maxim MAX16064"
default n
help
If you say yes here you get hardware monitoring support for Maxim
MAX16064.
This driver can also be built as a module. If so, the module will
be called max16064.
config SENSORS_MAX34440
tristate "Maxim MAX34440/MAX34441"
default n
help
If you say yes here you get hardware monitoring support for Maxim
MAX34440 and MAX34441.
This driver can also be built as a module. If so, the module will
be called max34440.
config SENSORS_MAX8688
tristate "Maxim MAX8688"
default n
help
If you say yes here you get hardware monitoring support for Maxim
MAX8688.
This driver can also be built as a module. If so, the module will
be called max8688.
config SENSORS_UCD9000
tristate "TI UCD90120, UCD90124, UCD9090, UCD90910"
default n
help
If you say yes here you get hardware monitoring support for TI
UCD90120, UCD90124, UCD9090, UCD90910 Sequencer and System Health
Controllers.
This driver can also be built as a module. If so, the module will
be called ucd9000.
config SENSORS_UCD9200
tristate "TI UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, UCD9248"
default n
help
If you say yes here you get hardware monitoring support for TI
UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, and UCD9248
Digital PWM System Controllers.
This driver can also be built as a module. If so, the module will
be called ucd9200.
endif # PMBUS
config SENSORS_SHT15 config SENSORS_SHT15
tristate "Sensiron humidity and temperature sensors. SHT15 and compat." tristate "Sensiron humidity and temperature sensors. SHT15 and compat."
......
...@@ -80,6 +80,7 @@ obj-$(CONFIG_SENSORS_LM90) += lm90.o ...@@ -80,6 +80,7 @@ obj-$(CONFIG_SENSORS_LM90) += lm90.o
obj-$(CONFIG_SENSORS_LM92) += lm92.o obj-$(CONFIG_SENSORS_LM92) += lm92.o
obj-$(CONFIG_SENSORS_LM93) += lm93.o obj-$(CONFIG_SENSORS_LM93) += lm93.o
obj-$(CONFIG_SENSORS_LM95241) += lm95241.o obj-$(CONFIG_SENSORS_LM95241) += lm95241.o
obj-$(CONFIG_SENSORS_LM95245) += lm95245.o
obj-$(CONFIG_SENSORS_LTC4151) += ltc4151.o obj-$(CONFIG_SENSORS_LTC4151) += ltc4151.o
obj-$(CONFIG_SENSORS_LTC4215) += ltc4215.o obj-$(CONFIG_SENSORS_LTC4215) += ltc4215.o
obj-$(CONFIG_SENSORS_LTC4245) += ltc4245.o obj-$(CONFIG_SENSORS_LTC4245) += ltc4245.o
...@@ -87,10 +88,12 @@ obj-$(CONFIG_SENSORS_LTC4261) += ltc4261.o ...@@ -87,10 +88,12 @@ obj-$(CONFIG_SENSORS_LTC4261) += ltc4261.o
obj-$(CONFIG_SENSORS_MAX1111) += max1111.o obj-$(CONFIG_SENSORS_MAX1111) += max1111.o
obj-$(CONFIG_SENSORS_MAX16065) += max16065.o obj-$(CONFIG_SENSORS_MAX16065) += max16065.o
obj-$(CONFIG_SENSORS_MAX1619) += max1619.o obj-$(CONFIG_SENSORS_MAX1619) += max1619.o
obj-$(CONFIG_SENSORS_MAX1668) += max1668.o
obj-$(CONFIG_SENSORS_MAX6639) += max6639.o obj-$(CONFIG_SENSORS_MAX6639) += max6639.o
obj-$(CONFIG_SENSORS_MAX6642) += max6642.o obj-$(CONFIG_SENSORS_MAX6642) += max6642.o
obj-$(CONFIG_SENSORS_MAX6650) += max6650.o obj-$(CONFIG_SENSORS_MAX6650) += max6650.o
obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o
obj-$(CONFIG_SENSORS_PC87360) += pc87360.o obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
obj-$(CONFIG_SENSORS_PC87427) += pc87427.o obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
...@@ -121,15 +124,7 @@ obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o ...@@ -121,15 +124,7 @@ obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o
obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o
obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o
# PMBus drivers obj-$(CONFIG_PMBUS) += pmbus/
obj-$(CONFIG_PMBUS) += pmbus_core.o
obj-$(CONFIG_SENSORS_PMBUS) += pmbus.o
obj-$(CONFIG_SENSORS_ADM1275) += adm1275.o
obj-$(CONFIG_SENSORS_MAX16064) += max16064.o
obj-$(CONFIG_SENSORS_MAX34440) += max34440.o
obj-$(CONFIG_SENSORS_MAX8688) += max8688.o
obj-$(CONFIG_SENSORS_UCD9000) += ucd9000.o
obj-$(CONFIG_SENSORS_UCD9200) += ucd9200.o
ccflags-$(CONFIG_HWMON_DEBUG_CHIP) := -DDEBUG ccflags-$(CONFIG_HWMON_DEBUG_CHIP) := -DDEBUG
...@@ -44,7 +44,9 @@ ...@@ -44,7 +44,9 @@
#define BASE_SYSFS_ATTR_NO 2 /* Sysfs Base attr no for coretemp */ #define BASE_SYSFS_ATTR_NO 2 /* Sysfs Base attr no for coretemp */
#define NUM_REAL_CORES 16 /* Number of Real cores per cpu */ #define NUM_REAL_CORES 16 /* Number of Real cores per cpu */
#define CORETEMP_NAME_LENGTH 17 /* String Length of attrs */ #define CORETEMP_NAME_LENGTH 17 /* String Length of attrs */
#define MAX_ATTRS 5 /* Maximum no of per-core attrs */ #define MAX_CORE_ATTRS 4 /* Maximum no of basic attrs */
#define MAX_THRESH_ATTRS 3 /* Maximum no of Threshold attrs */
#define TOTAL_ATTRS (MAX_CORE_ATTRS + MAX_THRESH_ATTRS)
#define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO) #define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO)
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
...@@ -67,6 +69,9 @@ ...@@ -67,6 +69,9 @@
* This value is passed as "id" field to rdmsr/wrmsr functions. * This value is passed as "id" field to rdmsr/wrmsr functions.
* @status_reg: One of IA32_THERM_STATUS or IA32_PACKAGE_THERM_STATUS, * @status_reg: One of IA32_THERM_STATUS or IA32_PACKAGE_THERM_STATUS,
* from where the temperature values should be read. * from where the temperature values should be read.
* @intrpt_reg: One of IA32_THERM_INTERRUPT or IA32_PACKAGE_THERM_INTERRUPT,
* from where the thresholds are read.
* @attr_size: Total number of pre-core attrs displayed in the sysfs.
* @is_pkg_data: If this is 1, the temp_data holds pkgtemp data. * @is_pkg_data: If this is 1, the temp_data holds pkgtemp data.
* Otherwise, temp_data holds coretemp data. * Otherwise, temp_data holds coretemp data.
* @valid: If this is 1, the current temperature is valid. * @valid: If this is 1, the current temperature is valid.
...@@ -74,15 +79,18 @@ ...@@ -74,15 +79,18 @@
struct temp_data { struct temp_data {
int temp; int temp;
int ttarget; int ttarget;
int tmin;
int tjmax; int tjmax;
unsigned long last_updated; unsigned long last_updated;
unsigned int cpu; unsigned int cpu;
u32 cpu_core_id; u32 cpu_core_id;
u32 status_reg; u32 status_reg;
u32 intrpt_reg;
int attr_size;
bool is_pkg_data; bool is_pkg_data;
bool valid; bool valid;
struct sensor_device_attribute sd_attrs[MAX_ATTRS]; struct sensor_device_attribute sd_attrs[TOTAL_ATTRS];
char attr_name[MAX_ATTRS][CORETEMP_NAME_LENGTH]; char attr_name[TOTAL_ATTRS][CORETEMP_NAME_LENGTH];
struct mutex update_lock; struct mutex update_lock;
}; };
...@@ -135,6 +143,19 @@ static ssize_t show_crit_alarm(struct device *dev, ...@@ -135,6 +143,19 @@ static ssize_t show_crit_alarm(struct device *dev,
return sprintf(buf, "%d\n", (eax >> 5) & 1); return sprintf(buf, "%d\n", (eax >> 5) & 1);
} }
static ssize_t show_max_alarm(struct device *dev,
struct device_attribute *devattr, char *buf)
{
u32 eax, edx;
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct platform_data *pdata = dev_get_drvdata(dev);
struct temp_data *tdata = pdata->core_data[attr->index];
rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx);
return sprintf(buf, "%d\n", !!(eax & THERM_STATUS_THRESHOLD1));
}
static ssize_t show_tjmax(struct device *dev, static ssize_t show_tjmax(struct device *dev,
struct device_attribute *devattr, char *buf) struct device_attribute *devattr, char *buf)
{ {
...@@ -153,6 +174,83 @@ static ssize_t show_ttarget(struct device *dev, ...@@ -153,6 +174,83 @@ static ssize_t show_ttarget(struct device *dev,
return sprintf(buf, "%d\n", pdata->core_data[attr->index]->ttarget); return sprintf(buf, "%d\n", pdata->core_data[attr->index]->ttarget);
} }
static ssize_t store_ttarget(struct device *dev,
struct device_attribute *devattr,
const char *buf, size_t count)
{
struct platform_data *pdata = dev_get_drvdata(dev);
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct temp_data *tdata = pdata->core_data[attr->index];
u32 eax, edx;
unsigned long val;
int diff;
if (strict_strtoul(buf, 10, &val))
return -EINVAL;
/*
* THERM_MASK_THRESHOLD1 is 7 bits wide. Values are entered in terms
* of milli degree celsius. Hence don't accept val > (127 * 1000)
*/
if (val > tdata->tjmax || val > 127000)
return -EINVAL;
diff = (tdata->tjmax - val) / 1000;
mutex_lock(&tdata->update_lock);
rdmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, &eax, &edx);
eax = (eax & ~THERM_MASK_THRESHOLD1) |
(diff << THERM_SHIFT_THRESHOLD1);
wrmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, eax, edx);
tdata->ttarget = val;
mutex_unlock(&tdata->update_lock);
return count;
}
static ssize_t show_tmin(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct platform_data *pdata = dev_get_drvdata(dev);
return sprintf(buf, "%d\n", pdata->core_data[attr->index]->tmin);
}
static ssize_t store_tmin(struct device *dev,
struct device_attribute *devattr,
const char *buf, size_t count)
{
struct platform_data *pdata = dev_get_drvdata(dev);
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct temp_data *tdata = pdata->core_data[attr->index];
u32 eax, edx;
unsigned long val;
int diff;
if (strict_strtoul(buf, 10, &val))
return -EINVAL;
/*
* THERM_MASK_THRESHOLD0 is 7 bits wide. Values are entered in terms
* of milli degree celsius. Hence don't accept val > (127 * 1000)
*/
if (val > tdata->tjmax || val > 127000)
return -EINVAL;
diff = (tdata->tjmax - val) / 1000;
mutex_lock(&tdata->update_lock);
rdmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, &eax, &edx);
eax = (eax & ~THERM_MASK_THRESHOLD0) |
(diff << THERM_SHIFT_THRESHOLD0);
wrmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, eax, edx);
tdata->tmin = val;
mutex_unlock(&tdata->update_lock);
return count;
}
static ssize_t show_temp(struct device *dev, static ssize_t show_temp(struct device *dev,
struct device_attribute *devattr, char *buf) struct device_attribute *devattr, char *buf)
{ {
...@@ -344,23 +442,31 @@ static int create_core_attrs(struct temp_data *tdata, struct device *dev, ...@@ -344,23 +442,31 @@ static int create_core_attrs(struct temp_data *tdata, struct device *dev,
int attr_no) int attr_no)
{ {
int err, i; int err, i;
static ssize_t (*rd_ptr[MAX_ATTRS]) (struct device *dev, static ssize_t (*rd_ptr[TOTAL_ATTRS]) (struct device *dev,
struct device_attribute *devattr, char *buf) = { struct device_attribute *devattr, char *buf) = {
show_label, show_crit_alarm, show_ttarget, show_label, show_crit_alarm, show_temp, show_tjmax,
show_temp, show_tjmax }; show_max_alarm, show_ttarget, show_tmin };
static const char *names[MAX_ATTRS] = { static ssize_t (*rw_ptr[TOTAL_ATTRS]) (struct device *dev,
struct device_attribute *devattr, const char *buf,
size_t count) = { NULL, NULL, NULL, NULL, NULL,
store_ttarget, store_tmin };
static const char *names[TOTAL_ATTRS] = {
"temp%d_label", "temp%d_crit_alarm", "temp%d_label", "temp%d_crit_alarm",
"temp%d_max", "temp%d_input", "temp%d_input", "temp%d_crit",
"temp%d_crit" }; "temp%d_max_alarm", "temp%d_max",
"temp%d_max_hyst" };
for (i = 0; i < MAX_ATTRS; i++) { for (i = 0; i < tdata->attr_size; i++) {
snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH, names[i], snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH, names[i],
attr_no); attr_no);
sysfs_attr_init(&tdata->sd_attrs[i].dev_attr.attr); sysfs_attr_init(&tdata->sd_attrs[i].dev_attr.attr);
tdata->sd_attrs[i].dev_attr.attr.name = tdata->attr_name[i]; tdata->sd_attrs[i].dev_attr.attr.name = tdata->attr_name[i];
tdata->sd_attrs[i].dev_attr.attr.mode = S_IRUGO; tdata->sd_attrs[i].dev_attr.attr.mode = S_IRUGO;
if (rw_ptr[i]) {
tdata->sd_attrs[i].dev_attr.attr.mode |= S_IWUSR;
tdata->sd_attrs[i].dev_attr.store = rw_ptr[i];
}
tdata->sd_attrs[i].dev_attr.show = rd_ptr[i]; tdata->sd_attrs[i].dev_attr.show = rd_ptr[i];
tdata->sd_attrs[i].dev_attr.store = NULL;
tdata->sd_attrs[i].index = attr_no; tdata->sd_attrs[i].index = attr_no;
err = device_create_file(dev, &tdata->sd_attrs[i].dev_attr); err = device_create_file(dev, &tdata->sd_attrs[i].dev_attr);
if (err) if (err)
...@@ -374,38 +480,6 @@ static int create_core_attrs(struct temp_data *tdata, struct device *dev, ...@@ -374,38 +480,6 @@ static int create_core_attrs(struct temp_data *tdata, struct device *dev,
return err; return err;
} }
static void update_ttarget(__u8 cpu_model, struct temp_data *tdata,
struct device *dev)
{
int err;
u32 eax, edx;
/*
* Initialize ttarget value. Eventually this will be
* initialized with the value from MSR_IA32_THERM_INTERRUPT
* register. If IA32_TEMPERATURE_TARGET is supported, this
* value will be over written below.
* To Do: Patch to initialize ttarget from MSR_IA32_THERM_INTERRUPT
*/
tdata->ttarget = tdata->tjmax - 20000;
/*
* Read the still undocumented IA32_TEMPERATURE_TARGET. It exists
* on older CPUs but not in this register,
* Atoms don't have it either.
*/
if (cpu_model > 0xe && cpu_model != 0x1c) {
err = rdmsr_safe_on_cpu(tdata->cpu,
MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
if (err) {
dev_warn(dev,
"Unable to read IA32_TEMPERATURE_TARGET MSR\n");
} else {
tdata->ttarget = tdata->tjmax -
((eax >> 8) & 0xff) * 1000;
}
}
}
static int __devinit chk_ucode_version(struct platform_device *pdev) static int __devinit chk_ucode_version(struct platform_device *pdev)
{ {
...@@ -464,9 +538,12 @@ static struct temp_data *init_temp_data(unsigned int cpu, int pkg_flag) ...@@ -464,9 +538,12 @@ static struct temp_data *init_temp_data(unsigned int cpu, int pkg_flag)
tdata->status_reg = pkg_flag ? MSR_IA32_PACKAGE_THERM_STATUS : tdata->status_reg = pkg_flag ? MSR_IA32_PACKAGE_THERM_STATUS :
MSR_IA32_THERM_STATUS; MSR_IA32_THERM_STATUS;
tdata->intrpt_reg = pkg_flag ? MSR_IA32_PACKAGE_THERM_INTERRUPT :
MSR_IA32_THERM_INTERRUPT;
tdata->is_pkg_data = pkg_flag; tdata->is_pkg_data = pkg_flag;
tdata->cpu = cpu; tdata->cpu = cpu;
tdata->cpu_core_id = TO_CORE_ID(cpu); tdata->cpu_core_id = TO_CORE_ID(cpu);
tdata->attr_size = MAX_CORE_ATTRS;
mutex_init(&tdata->update_lock); mutex_init(&tdata->update_lock);
return tdata; return tdata;
} }
...@@ -516,7 +593,17 @@ static int create_core_data(struct platform_data *pdata, ...@@ -516,7 +593,17 @@ static int create_core_data(struct platform_data *pdata,
else else
tdata->tjmax = get_tjmax(c, cpu, &pdev->dev); tdata->tjmax = get_tjmax(c, cpu, &pdev->dev);
update_ttarget(c->x86_model, tdata, &pdev->dev); /*
* Test if we can access the intrpt register. If so, increase the
* 'size' enough to have ttarget/tmin/max_alarm interfaces.
* Initialize ttarget with bits 16:22 of MSR_IA32_THERM_INTERRUPT
*/
err = rdmsr_safe_on_cpu(cpu, tdata->intrpt_reg, &eax, &edx);
if (!err) {
tdata->attr_size += MAX_THRESH_ATTRS;
tdata->ttarget = tdata->tjmax - ((eax >> 16) & 0x7f) * 1000;
}
pdata->core_data[attr_no] = tdata; pdata->core_data[attr_no] = tdata;
/* Create sysfs interfaces */ /* Create sysfs interfaces */
...@@ -553,7 +640,7 @@ static void coretemp_remove_core(struct platform_data *pdata, ...@@ -553,7 +640,7 @@ static void coretemp_remove_core(struct platform_data *pdata,
struct temp_data *tdata = pdata->core_data[indx]; struct temp_data *tdata = pdata->core_data[indx];
/* Remove the sysfs attributes */ /* Remove the sysfs attributes */
for (i = 0; i < MAX_ATTRS; i++) for (i = 0; i < tdata->attr_size; i++)
device_remove_file(dev, &tdata->sd_attrs[i].dev_attr); device_remove_file(dev, &tdata->sd_attrs[i].dev_attr);
kfree(pdata->core_data[indx]); kfree(pdata->core_data[indx]);
......
...@@ -54,6 +54,9 @@ ...@@ -54,6 +54,9 @@
* and extended mode. They are mostly compatible with LM90 except for a data * and extended mode. They are mostly compatible with LM90 except for a data
* format difference for the temperature value registers. * format difference for the temperature value registers.
* *
* This driver also supports the SA56004 from Philips. This device is
* pin-compatible with the LM86, the ED/EDP parts are also address-compatible.
*
* Since the LM90 was the first chipset supported by this driver, most * Since the LM90 was the first chipset supported by this driver, most
* comments will refer to this chipset, but are actually general and * comments will refer to this chipset, but are actually general and
* concern all supported chipsets, unless mentioned otherwise. * concern all supported chipsets, unless mentioned otherwise.
...@@ -96,13 +99,15 @@ ...@@ -96,13 +99,15 @@
* MAX6659 can have address 0x4c, 0x4d or 0x4e. * MAX6659 can have address 0x4c, 0x4d or 0x4e.
* MAX6680 and MAX6681 can have address 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, * MAX6680 and MAX6681 can have address 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b,
* 0x4c, 0x4d or 0x4e. * 0x4c, 0x4d or 0x4e.
* SA56004 can have address 0x48 through 0x4F.
*/ */
static const unsigned short normal_i2c[] = { static const unsigned short normal_i2c[] = {
0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END }; 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x48, 0x49, 0x4a, 0x4b, 0x4c,
0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680,
max6646, w83l771, max6696 }; max6646, w83l771, max6696, sa56004 };
/* /*
* The LM90 registers * The LM90 registers
...@@ -152,6 +157,10 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, ...@@ -152,6 +157,10 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680,
#define MAX6659_REG_R_LOCAL_EMERG 0x17 #define MAX6659_REG_R_LOCAL_EMERG 0x17
#define MAX6659_REG_W_LOCAL_EMERG 0x17 #define MAX6659_REG_W_LOCAL_EMERG 0x17
/* SA56004 registers */
#define SA56004_REG_R_LOCAL_TEMPL 0x22
#define LM90_DEF_CONVRATE_RVAL 6 /* Def conversion rate register value */ #define LM90_DEF_CONVRATE_RVAL 6 /* Def conversion rate register value */
#define LM90_MAX_CONVRATE_MS 16000 /* Maximum conversion rate in ms */ #define LM90_MAX_CONVRATE_MS 16000 /* Maximum conversion rate in ms */
...@@ -161,7 +170,6 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, ...@@ -161,7 +170,6 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680,
#define LM90_FLAG_ADT7461_EXT (1 << 0) /* ADT7461 extended mode */ #define LM90_FLAG_ADT7461_EXT (1 << 0) /* ADT7461 extended mode */
/* Device features */ /* Device features */
#define LM90_HAVE_OFFSET (1 << 1) /* temperature offset register */ #define LM90_HAVE_OFFSET (1 << 1) /* temperature offset register */
#define LM90_HAVE_LOCAL_EXT (1 << 2) /* extended local temperature */
#define LM90_HAVE_REM_LIMIT_EXT (1 << 3) /* extended remote limit */ #define LM90_HAVE_REM_LIMIT_EXT (1 << 3) /* extended remote limit */
#define LM90_HAVE_EMERGENCY (1 << 4) /* 3rd upper (emergency) limit */ #define LM90_HAVE_EMERGENCY (1 << 4) /* 3rd upper (emergency) limit */
#define LM90_HAVE_EMERGENCY_ALARM (1 << 5)/* emergency alarm */ #define LM90_HAVE_EMERGENCY_ALARM (1 << 5)/* emergency alarm */
...@@ -192,6 +200,7 @@ static const struct i2c_device_id lm90_id[] = { ...@@ -192,6 +200,7 @@ static const struct i2c_device_id lm90_id[] = {
{ "max6696", max6696 }, { "max6696", max6696 },
{ "nct1008", adt7461 }, { "nct1008", adt7461 },
{ "w83l771", w83l771 }, { "w83l771", w83l771 },
{ "sa56004", sa56004 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, lm90_id); MODULE_DEVICE_TABLE(i2c, lm90_id);
...@@ -204,6 +213,7 @@ struct lm90_params { ...@@ -204,6 +213,7 @@ struct lm90_params {
u16 alert_alarms; /* Which alarm bits trigger ALERT# */ u16 alert_alarms; /* Which alarm bits trigger ALERT# */
/* Upper 8 bits for max6695/96 */ /* Upper 8 bits for max6695/96 */
u8 max_convrate; /* Maximum conversion rate register value */ u8 max_convrate; /* Maximum conversion rate register value */
u8 reg_local_ext; /* Extended local temp register (optional) */
}; };
static const struct lm90_params lm90_params[] = { static const struct lm90_params lm90_params[] = {
...@@ -235,19 +245,20 @@ static const struct lm90_params lm90_params[] = { ...@@ -235,19 +245,20 @@ static const struct lm90_params lm90_params[] = {
.max_convrate = 9, .max_convrate = 9,
}, },
[max6646] = { [max6646] = {
.flags = LM90_HAVE_LOCAL_EXT,
.alert_alarms = 0x7c, .alert_alarms = 0x7c,
.max_convrate = 6, .max_convrate = 6,
.reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL,
}, },
[max6657] = { [max6657] = {
.flags = LM90_HAVE_LOCAL_EXT,
.alert_alarms = 0x7c, .alert_alarms = 0x7c,
.max_convrate = 8, .max_convrate = 8,
.reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL,
}, },
[max6659] = { [max6659] = {
.flags = LM90_HAVE_LOCAL_EXT | LM90_HAVE_EMERGENCY, .flags = LM90_HAVE_EMERGENCY,
.alert_alarms = 0x7c, .alert_alarms = 0x7c,
.max_convrate = 8, .max_convrate = 8,
.reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL,
}, },
[max6680] = { [max6680] = {
.flags = LM90_HAVE_OFFSET, .flags = LM90_HAVE_OFFSET,
...@@ -255,16 +266,23 @@ static const struct lm90_params lm90_params[] = { ...@@ -255,16 +266,23 @@ static const struct lm90_params lm90_params[] = {
.max_convrate = 7, .max_convrate = 7,
}, },
[max6696] = { [max6696] = {
.flags = LM90_HAVE_LOCAL_EXT | LM90_HAVE_EMERGENCY .flags = LM90_HAVE_EMERGENCY
| LM90_HAVE_EMERGENCY_ALARM | LM90_HAVE_TEMP3, | LM90_HAVE_EMERGENCY_ALARM | LM90_HAVE_TEMP3,
.alert_alarms = 0x187c, .alert_alarms = 0x187c,
.max_convrate = 6, .max_convrate = 6,
.reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL,
}, },
[w83l771] = { [w83l771] = {
.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT, .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT,
.alert_alarms = 0x7c, .alert_alarms = 0x7c,
.max_convrate = 8, .max_convrate = 8,
}, },
[sa56004] = {
.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT,
.alert_alarms = 0x7b,
.max_convrate = 9,
.reg_local_ext = SA56004_REG_R_LOCAL_TEMPL,
},
}; };
/* /*
...@@ -286,6 +304,7 @@ struct lm90_data { ...@@ -286,6 +304,7 @@ struct lm90_data {
u16 alert_alarms; /* Which alarm bits trigger ALERT# */ u16 alert_alarms; /* Which alarm bits trigger ALERT# */
/* Upper 8 bits for max6695/96 */ /* Upper 8 bits for max6695/96 */
u8 max_convrate; /* Maximum conversion rate */ u8 max_convrate; /* Maximum conversion rate */
u8 reg_local_ext; /* local extension register offset */
/* registers values */ /* registers values */
s8 temp8[8]; /* 0: local low limit s8 temp8[8]; /* 0: local low limit
...@@ -452,9 +471,9 @@ static struct lm90_data *lm90_update_device(struct device *dev) ...@@ -452,9 +471,9 @@ static struct lm90_data *lm90_update_device(struct device *dev)
lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, &data->temp8[3]); lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, &data->temp8[3]);
lm90_read_reg(client, LM90_REG_R_TCRIT_HYST, &data->temp_hyst); lm90_read_reg(client, LM90_REG_R_TCRIT_HYST, &data->temp_hyst);
if (data->flags & LM90_HAVE_LOCAL_EXT) { if (data->reg_local_ext) {
lm90_read16(client, LM90_REG_R_LOCAL_TEMP, lm90_read16(client, LM90_REG_R_LOCAL_TEMP,
MAX6657_REG_R_LOCAL_TEMPL, data->reg_local_ext,
&data->temp11[4]); &data->temp11[4]);
} else { } else {
if (lm90_read_reg(client, LM90_REG_R_LOCAL_TEMP, if (lm90_read_reg(client, LM90_REG_R_LOCAL_TEMP,
...@@ -1092,7 +1111,7 @@ static int lm90_detect(struct i2c_client *new_client, ...@@ -1092,7 +1111,7 @@ static int lm90_detect(struct i2c_client *new_client,
struct i2c_adapter *adapter = new_client->adapter; struct i2c_adapter *adapter = new_client->adapter;
int address = new_client->addr; int address = new_client->addr;
const char *name = NULL; const char *name = NULL;
int man_id, chip_id, reg_config1, reg_convrate; int man_id, chip_id, reg_config1, reg_config2, reg_convrate;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV; return -ENODEV;
...@@ -1108,15 +1127,16 @@ static int lm90_detect(struct i2c_client *new_client, ...@@ -1108,15 +1127,16 @@ static int lm90_detect(struct i2c_client *new_client,
LM90_REG_R_CONVRATE)) < 0) LM90_REG_R_CONVRATE)) < 0)
return -ENODEV; return -ENODEV;
if ((address == 0x4C || address == 0x4D) if (man_id == 0x01 || man_id == 0x5C || man_id == 0x41) {
&& man_id == 0x01) { /* National Semiconductor */
int reg_config2;
reg_config2 = i2c_smbus_read_byte_data(new_client, reg_config2 = i2c_smbus_read_byte_data(new_client,
LM90_REG_R_CONFIG2); LM90_REG_R_CONFIG2);
if (reg_config2 < 0) if (reg_config2 < 0)
return -ENODEV; return -ENODEV;
} else
reg_config2 = 0; /* Make compiler happy */
if ((address == 0x4C || address == 0x4D)
&& man_id == 0x01) { /* National Semiconductor */
if ((reg_config1 & 0x2A) == 0x00 if ((reg_config1 & 0x2A) == 0x00
&& (reg_config2 & 0xF8) == 0x00 && (reg_config2 & 0xF8) == 0x00
&& reg_convrate <= 0x09) { && reg_convrate <= 0x09) {
...@@ -1245,13 +1265,6 @@ static int lm90_detect(struct i2c_client *new_client, ...@@ -1245,13 +1265,6 @@ static int lm90_detect(struct i2c_client *new_client,
} else } else
if (address == 0x4C if (address == 0x4C
&& man_id == 0x5C) { /* Winbond/Nuvoton */ && man_id == 0x5C) { /* Winbond/Nuvoton */
int reg_config2;
reg_config2 = i2c_smbus_read_byte_data(new_client,
LM90_REG_R_CONFIG2);
if (reg_config2 < 0)
return -ENODEV;
if ((reg_config1 & 0x2A) == 0x00 if ((reg_config1 & 0x2A) == 0x00
&& (reg_config2 & 0xF8) == 0x00) { && (reg_config2 & 0xF8) == 0x00) {
if (chip_id == 0x01 /* W83L771W/G */ if (chip_id == 0x01 /* W83L771W/G */
...@@ -1263,6 +1276,15 @@ static int lm90_detect(struct i2c_client *new_client, ...@@ -1263,6 +1276,15 @@ static int lm90_detect(struct i2c_client *new_client,
name = "w83l771"; name = "w83l771";
} }
} }
} else
if (address >= 0x48 && address <= 0x4F
&& man_id == 0xA1) { /* NXP Semiconductor/Philips */
if (chip_id == 0x00
&& (reg_config1 & 0x2A) == 0x00
&& (reg_config2 & 0xFE) == 0x00
&& reg_convrate <= 0x09) {
name = "sa56004";
}
} }
if (!name) { /* identification failed */ if (!name) { /* identification failed */
...@@ -1368,6 +1390,7 @@ static int lm90_probe(struct i2c_client *new_client, ...@@ -1368,6 +1390,7 @@ static int lm90_probe(struct i2c_client *new_client,
/* Set chip capabilities */ /* Set chip capabilities */
data->flags = lm90_params[data->kind].flags; data->flags = lm90_params[data->kind].flags;
data->reg_local_ext = lm90_params[data->kind].reg_local_ext;
/* Set maximum conversion rate */ /* Set maximum conversion rate */
data->max_convrate = lm90_params[data->kind].max_convrate; data->max_convrate = lm90_params[data->kind].max_convrate;
......
...@@ -74,8 +74,9 @@ static const unsigned short normal_i2c[] = { ...@@ -74,8 +74,9 @@ static const unsigned short normal_i2c[] = {
#define TT_OFF 0 #define TT_OFF 0
#define TT_ON 1 #define TT_ON 1
#define TT_MASK 7 #define TT_MASK 7
#define MANUFACTURER_ID 0x01 #define NATSEMI_MAN_ID 0x01
#define DEFAULT_REVISION 0xA4 #define LM95231_CHIP_ID 0xA1
#define LM95241_CHIP_ID 0xA4
static const u8 lm95241_reg_address[] = { static const u8 lm95241_reg_address[] = {
LM95241_REG_R_LOCAL_TEMPH, LM95241_REG_R_LOCAL_TEMPH,
...@@ -338,20 +339,25 @@ static int lm95241_detect(struct i2c_client *new_client, ...@@ -338,20 +339,25 @@ static int lm95241_detect(struct i2c_client *new_client,
struct i2c_board_info *info) struct i2c_board_info *info)
{ {
struct i2c_adapter *adapter = new_client->adapter; struct i2c_adapter *adapter = new_client->adapter;
int address = new_client->addr;
const char *name; const char *name;
int mfg_id, chip_id;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV; return -ENODEV;
if ((i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID) mfg_id = i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID);
== MANUFACTURER_ID) if (mfg_id != NATSEMI_MAN_ID)
&& (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID) return -ENODEV;
== DEFAULT_REVISION)) {
name = DEVNAME; chip_id = i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID);
} else { switch (chip_id) {
dev_dbg(&adapter->dev, "LM95241 detection failed at 0x%02x\n", case LM95231_CHIP_ID:
address); name = "lm95231";
break;
case LM95241_CHIP_ID:
name = "lm95241";
break;
default:
return -ENODEV; return -ENODEV;
} }
...@@ -431,7 +437,8 @@ static int lm95241_remove(struct i2c_client *client) ...@@ -431,7 +437,8 @@ static int lm95241_remove(struct i2c_client *client)
/* Driver data (common to all clients) */ /* Driver data (common to all clients) */
static const struct i2c_device_id lm95241_id[] = { static const struct i2c_device_id lm95241_id[] = {
{ DEVNAME, 0 }, { "lm95231", 0 },
{ "lm95241", 0 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, lm95241_id); MODULE_DEVICE_TABLE(i2c, lm95241_id);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#
# PMBus chip drivers configuration
#
menuconfig PMBUS
tristate "PMBus support"
depends on I2C && EXPERIMENTAL
default n
help
Say yes here if you want to enable PMBus support.
This driver can also be built as a module. If so, the module will
be called pmbus_core.
if PMBUS
config SENSORS_PMBUS
tristate "Generic PMBus devices"
default y
help
If you say yes here you get hardware monitoring support for generic
PMBus devices, including but not limited to ADP4000, BMR450, BMR451,
BMR453, BMR454, LTC2978, NCP4200, and NCP4208.
This driver can also be built as a module. If so, the module will
be called pmbus.
config SENSORS_ADM1275
tristate "Analog Devices ADM1275"
default n
help
If you say yes here you get hardware monitoring support for Analog
Devices ADM1275 Hot-Swap Controller and Digital Power Monitor.
This driver can also be built as a module. If so, the module will
be called adm1275.
config SENSORS_LM25066
tristate "National Semiconductor LM25066 and compatibles"
default n
help
If you say yes here you get hardware monitoring support for National
Semiconductor LM25066, LM5064, and LM5066.
This driver can also be built as a module. If so, the module will
be called lm25066.
config SENSORS_MAX16064
tristate "Maxim MAX16064"
default n
help
If you say yes here you get hardware monitoring support for Maxim
MAX16064.
This driver can also be built as a module. If so, the module will
be called max16064.
config SENSORS_MAX34440
tristate "Maxim MAX34440/MAX34441"
default n
help
If you say yes here you get hardware monitoring support for Maxim
MAX34440 and MAX34441.
This driver can also be built as a module. If so, the module will
be called max34440.
config SENSORS_MAX8688
tristate "Maxim MAX8688"
default n
help
If you say yes here you get hardware monitoring support for Maxim
MAX8688.
This driver can also be built as a module. If so, the module will
be called max8688.
config SENSORS_UCD9000
tristate "TI UCD90120, UCD90124, UCD9090, UCD90910"
default n
help
If you say yes here you get hardware monitoring support for TI
UCD90120, UCD90124, UCD9090, UCD90910 Sequencer and System Health
Controllers.
This driver can also be built as a module. If so, the module will
be called ucd9000.
config SENSORS_UCD9200
tristate "TI UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, UCD9248"
default n
help
If you say yes here you get hardware monitoring support for TI
UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, and UCD9248
Digital PWM System Controllers.
This driver can also be built as a module. If so, the module will
be called ucd9200.
endif # PMBUS
#
# Makefile for PMBus chip drivers.
#
obj-$(CONFIG_PMBUS) += pmbus_core.o
obj-$(CONFIG_SENSORS_PMBUS) += pmbus.o
obj-$(CONFIG_SENSORS_ADM1275) += adm1275.o
obj-$(CONFIG_SENSORS_LM25066) += lm25066.o
obj-$(CONFIG_SENSORS_MAX16064) += max16064.o
obj-$(CONFIG_SENSORS_MAX34440) += max34440.o
obj-$(CONFIG_SENSORS_MAX8688) += max8688.o
obj-$(CONFIG_SENSORS_UCD9000) += ucd9000.o
obj-$(CONFIG_SENSORS_UCD9200) += ucd9200.o
...@@ -23,11 +23,68 @@ ...@@ -23,11 +23,68 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include "pmbus.h" #include "pmbus.h"
#define ADM1275_PEAK_IOUT 0xd0
#define ADM1275_PEAK_VIN 0xd1
#define ADM1275_PEAK_VOUT 0xd2
#define ADM1275_PMON_CONFIG 0xd4 #define ADM1275_PMON_CONFIG 0xd4
#define ADM1275_VIN_VOUT_SELECT (1 << 6) #define ADM1275_VIN_VOUT_SELECT (1 << 6)
#define ADM1275_VRANGE (1 << 5) #define ADM1275_VRANGE (1 << 5)
static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
{
int ret;
if (page)
return -EINVAL;
switch (reg) {
case PMBUS_VIRT_READ_IOUT_MAX:
ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_IOUT);
break;
case PMBUS_VIRT_READ_VOUT_MAX:
ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VOUT);
break;
case PMBUS_VIRT_READ_VIN_MAX:
ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VIN);
break;
case PMBUS_VIRT_RESET_IOUT_HISTORY:
case PMBUS_VIRT_RESET_VOUT_HISTORY:
case PMBUS_VIRT_RESET_VIN_HISTORY:
ret = 0;
break;
default:
ret = -ENODATA;
break;
}
return ret;
}
static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
u16 word)
{
int ret;
if (page)
return -EINVAL;
switch (reg) {
case PMBUS_VIRT_RESET_IOUT_HISTORY:
ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_IOUT, 0);
break;
case PMBUS_VIRT_RESET_VOUT_HISTORY:
ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VOUT, 0);
break;
case PMBUS_VIRT_RESET_VIN_HISTORY:
ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VIN, 0);
break;
default:
ret = -ENODATA;
break;
}
return ret;
}
static int adm1275_probe(struct i2c_client *client, static int adm1275_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
...@@ -50,14 +107,17 @@ static int adm1275_probe(struct i2c_client *client, ...@@ -50,14 +107,17 @@ static int adm1275_probe(struct i2c_client *client,
} }
info->pages = 1; info->pages = 1;
info->direct[PSC_VOLTAGE_IN] = true; info->format[PSC_VOLTAGE_IN] = direct;
info->direct[PSC_VOLTAGE_OUT] = true; info->format[PSC_VOLTAGE_OUT] = direct;
info->direct[PSC_CURRENT_OUT] = true; info->format[PSC_CURRENT_OUT] = direct;
info->m[PSC_CURRENT_OUT] = 807; info->m[PSC_CURRENT_OUT] = 807;
info->b[PSC_CURRENT_OUT] = 20475; info->b[PSC_CURRENT_OUT] = 20475;
info->R[PSC_CURRENT_OUT] = -1; info->R[PSC_CURRENT_OUT] = -1;
info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT; info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
info->read_word_data = adm1275_read_word_data;
info->write_word_data = adm1275_write_word_data;
if (config & ADM1275_VRANGE) { if (config & ADM1275_VRANGE) {
info->m[PSC_VOLTAGE_IN] = 19199; info->m[PSC_VOLTAGE_IN] = 19199;
info->b[PSC_VOLTAGE_IN] = 0; info->b[PSC_VOLTAGE_IN] = 0;
......
/*
* Hardware monitoring driver for LM25066 / LM5064 / LM5066
*
* Copyright (c) 2011 Ericsson AB.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include "pmbus.h"
enum chips { lm25066, lm5064, lm5066 };
#define LM25066_READ_VAUX 0xd0
#define LM25066_MFR_READ_IIN 0xd1
#define LM25066_MFR_READ_PIN 0xd2
#define LM25066_MFR_IIN_OC_WARN_LIMIT 0xd3
#define LM25066_MFR_PIN_OP_WARN_LIMIT 0xd4
#define LM25066_READ_PIN_PEAK 0xd5
#define LM25066_CLEAR_PIN_PEAK 0xd6
#define LM25066_DEVICE_SETUP 0xd9
#define LM25066_READ_AVG_VIN 0xdc
#define LM25066_READ_AVG_VOUT 0xdd
#define LM25066_READ_AVG_IIN 0xde
#define LM25066_READ_AVG_PIN 0xdf
#define LM25066_DEV_SETUP_CL (1 << 4) /* Current limit */
struct lm25066_data {
int id;
struct pmbus_driver_info info;
};
#define to_lm25066_data(x) container_of(x, struct lm25066_data, info)
static int lm25066_read_word_data(struct i2c_client *client, int page, int reg)
{
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
const struct lm25066_data *data = to_lm25066_data(info);
int ret;
if (page > 1)
return -EINVAL;
/* Map READ_VAUX into READ_VOUT register on page 1 */
if (page == 1) {
switch (reg) {
case PMBUS_READ_VOUT:
ret = pmbus_read_word_data(client, 0,
LM25066_READ_VAUX);
if (ret < 0)
break;
/* Adjust returned value to match VOUT coefficients */
switch (data->id) {
case lm25066:
/* VOUT: 4.54 mV VAUX: 283.2 uV LSB */
ret = DIV_ROUND_CLOSEST(ret * 2832, 45400);
break;
case lm5064:
/* VOUT: 4.53 mV VAUX: 700 uV LSB */
ret = DIV_ROUND_CLOSEST(ret * 70, 453);
break;
case lm5066:
/* VOUT: 2.18 mV VAUX: 725 uV LSB */
ret = DIV_ROUND_CLOSEST(ret * 725, 2180);
break;
}
break;
default:
/* No other valid registers on page 1 */
ret = -EINVAL;
break;
}
goto done;
}
switch (reg) {
case PMBUS_READ_IIN:
ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_IIN);
break;
case PMBUS_READ_PIN:
ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_PIN);
break;
case PMBUS_IIN_OC_WARN_LIMIT:
ret = pmbus_read_word_data(client, 0,
LM25066_MFR_IIN_OC_WARN_LIMIT);
break;
case PMBUS_PIN_OP_WARN_LIMIT:
ret = pmbus_read_word_data(client, 0,
LM25066_MFR_PIN_OP_WARN_LIMIT);
break;
case PMBUS_VIRT_READ_VIN_AVG:
ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VIN);
break;
case PMBUS_VIRT_READ_VOUT_AVG:
ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VOUT);
break;
case PMBUS_VIRT_READ_IIN_AVG:
ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_IIN);
break;
case PMBUS_VIRT_READ_PIN_AVG:
ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_PIN);
break;
case PMBUS_VIRT_READ_PIN_MAX:
ret = pmbus_read_word_data(client, 0, LM25066_READ_PIN_PEAK);
break;
case PMBUS_VIRT_RESET_PIN_HISTORY:
ret = 0;
break;
default:
ret = -ENODATA;
break;
}
done:
return ret;
}
static int lm25066_write_word_data(struct i2c_client *client, int page, int reg,
u16 word)
{
int ret;
if (page > 1)
return -EINVAL;
switch (reg) {
case PMBUS_IIN_OC_WARN_LIMIT:
ret = pmbus_write_word_data(client, 0,
LM25066_MFR_IIN_OC_WARN_LIMIT,
word);
break;
case PMBUS_PIN_OP_WARN_LIMIT:
ret = pmbus_write_word_data(client, 0,
LM25066_MFR_PIN_OP_WARN_LIMIT,
word);
break;
case PMBUS_VIRT_RESET_PIN_HISTORY:
ret = pmbus_write_byte(client, 0, LM25066_CLEAR_PIN_PEAK);
break;
default:
ret = -ENODATA;
break;
}
return ret;
}
static int lm25066_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int config;
int ret;
struct lm25066_data *data;
struct pmbus_driver_info *info;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_READ_BYTE_DATA))
return -ENODEV;
data = kzalloc(sizeof(struct lm25066_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
config = i2c_smbus_read_byte_data(client, LM25066_DEVICE_SETUP);
if (config < 0) {
ret = config;
goto err_mem;
}
data->id = id->driver_data;
info = &data->info;
info->pages = 2;
info->format[PSC_VOLTAGE_IN] = direct;
info->format[PSC_VOLTAGE_OUT] = direct;
info->format[PSC_CURRENT_IN] = direct;
info->format[PSC_TEMPERATURE] = direct;
info->format[PSC_POWER] = direct;
info->m[PSC_TEMPERATURE] = 16;
info->b[PSC_TEMPERATURE] = 0;
info->R[PSC_TEMPERATURE] = 0;
info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT
| PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_PIN | PMBUS_HAVE_IIN
| PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
info->func[1] = PMBUS_HAVE_VOUT;
info->read_word_data = lm25066_read_word_data;
info->write_word_data = lm25066_write_word_data;
switch (id->driver_data) {
case lm25066:
info->m[PSC_VOLTAGE_IN] = 22070;
info->b[PSC_VOLTAGE_IN] = 0;
info->R[PSC_VOLTAGE_IN] = -2;
info->m[PSC_VOLTAGE_OUT] = 22070;
info->b[PSC_VOLTAGE_OUT] = 0;
info->R[PSC_VOLTAGE_OUT] = -2;
if (config & LM25066_DEV_SETUP_CL) {
info->m[PSC_CURRENT_IN] = 6852;
info->b[PSC_CURRENT_IN] = 0;
info->R[PSC_CURRENT_IN] = -2;
info->m[PSC_POWER] = 369;
info->b[PSC_POWER] = 0;
info->R[PSC_POWER] = -2;
} else {
info->m[PSC_CURRENT_IN] = 13661;
info->b[PSC_CURRENT_IN] = 0;
info->R[PSC_CURRENT_IN] = -2;
info->m[PSC_POWER] = 736;
info->b[PSC_POWER] = 0;
info->R[PSC_POWER] = -2;
}
break;
case lm5064:
info->m[PSC_VOLTAGE_IN] = 22075;
info->b[PSC_VOLTAGE_IN] = 0;
info->R[PSC_VOLTAGE_IN] = -2;
info->m[PSC_VOLTAGE_OUT] = 22075;
info->b[PSC_VOLTAGE_OUT] = 0;
info->R[PSC_VOLTAGE_OUT] = -2;
if (config & LM25066_DEV_SETUP_CL) {
info->m[PSC_CURRENT_IN] = 6713;
info->b[PSC_CURRENT_IN] = 0;
info->R[PSC_CURRENT_IN] = -2;
info->m[PSC_POWER] = 3619;
info->b[PSC_POWER] = 0;
info->R[PSC_POWER] = -3;
} else {
info->m[PSC_CURRENT_IN] = 13426;
info->b[PSC_CURRENT_IN] = 0;
info->R[PSC_CURRENT_IN] = -2;
info->m[PSC_POWER] = 7238;
info->b[PSC_POWER] = 0;
info->R[PSC_POWER] = -3;
}
break;
case lm5066:
info->m[PSC_VOLTAGE_IN] = 4587;
info->b[PSC_VOLTAGE_IN] = 0;
info->R[PSC_VOLTAGE_IN] = -2;
info->m[PSC_VOLTAGE_OUT] = 4587;
info->b[PSC_VOLTAGE_OUT] = 0;
info->R[PSC_VOLTAGE_OUT] = -2;
if (config & LM25066_DEV_SETUP_CL) {
info->m[PSC_CURRENT_IN] = 10753;
info->b[PSC_CURRENT_IN] = 0;
info->R[PSC_CURRENT_IN] = -2;
info->m[PSC_POWER] = 1204;
info->b[PSC_POWER] = 0;
info->R[PSC_POWER] = -3;
} else {
info->m[PSC_CURRENT_IN] = 5405;
info->b[PSC_CURRENT_IN] = 0;
info->R[PSC_CURRENT_IN] = -2;
info->m[PSC_POWER] = 605;
info->b[PSC_POWER] = 0;
info->R[PSC_POWER] = -3;
}
break;
default:
ret = -ENODEV;
goto err_mem;
}
ret = pmbus_do_probe(client, id, info);
if (ret)
goto err_mem;
return 0;
err_mem:
kfree(data);
return ret;
}
static int lm25066_remove(struct i2c_client *client)
{
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
const struct lm25066_data *data = to_lm25066_data(info);
int ret;
ret = pmbus_do_remove(client);
kfree(data);
return ret;
}
static const struct i2c_device_id lm25066_id[] = {
{"lm25066", lm25066},
{"lm5064", lm5064},
{"lm5066", lm5066},
{ }
};
MODULE_DEVICE_TABLE(i2c, lm25066_id);
/* This is the driver that will be inserted */
static struct i2c_driver lm25066_driver = {
.driver = {
.name = "lm25066",
},
.probe = lm25066_probe,
.remove = lm25066_remove,
.id_table = lm25066_id,
};
static int __init lm25066_init(void)
{
return i2c_add_driver(&lm25066_driver);
}
static void __exit lm25066_exit(void)
{
i2c_del_driver(&lm25066_driver);
}
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for LM25066/LM5064/LM5066");
MODULE_LICENSE("GPL");
module_init(lm25066_init);
module_exit(lm25066_exit);
...@@ -25,11 +25,60 @@ ...@@ -25,11 +25,60 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include "pmbus.h" #include "pmbus.h"
#define MAX16064_MFR_VOUT_PEAK 0xd4
#define MAX16064_MFR_TEMPERATURE_PEAK 0xd6
static int max16064_read_word_data(struct i2c_client *client, int page, int reg)
{
int ret;
switch (reg) {
case PMBUS_VIRT_READ_VOUT_MAX:
ret = pmbus_read_word_data(client, page,
MAX16064_MFR_VOUT_PEAK);
break;
case PMBUS_VIRT_READ_TEMP_MAX:
ret = pmbus_read_word_data(client, page,
MAX16064_MFR_TEMPERATURE_PEAK);
break;
case PMBUS_VIRT_RESET_VOUT_HISTORY:
case PMBUS_VIRT_RESET_TEMP_HISTORY:
ret = 0;
break;
default:
ret = -ENODATA;
break;
}
return ret;
}
static int max16064_write_word_data(struct i2c_client *client, int page,
int reg, u16 word)
{
int ret;
switch (reg) {
case PMBUS_VIRT_RESET_VOUT_HISTORY:
ret = pmbus_write_word_data(client, page,
MAX16064_MFR_VOUT_PEAK, 0);
break;
case PMBUS_VIRT_RESET_TEMP_HISTORY:
ret = pmbus_write_word_data(client, page,
MAX16064_MFR_TEMPERATURE_PEAK,
0xffff);
break;
default:
ret = -ENODATA;
break;
}
return ret;
}
static struct pmbus_driver_info max16064_info = { static struct pmbus_driver_info max16064_info = {
.pages = 4, .pages = 4,
.direct[PSC_VOLTAGE_IN] = true, .format[PSC_VOLTAGE_IN] = direct,
.direct[PSC_VOLTAGE_OUT] = true, .format[PSC_VOLTAGE_OUT] = direct,
.direct[PSC_TEMPERATURE] = true, .format[PSC_TEMPERATURE] = direct,
.m[PSC_VOLTAGE_IN] = 19995, .m[PSC_VOLTAGE_IN] = 19995,
.b[PSC_VOLTAGE_IN] = 0, .b[PSC_VOLTAGE_IN] = 0,
.R[PSC_VOLTAGE_IN] = -1, .R[PSC_VOLTAGE_IN] = -1,
...@@ -44,6 +93,8 @@ static struct pmbus_driver_info max16064_info = { ...@@ -44,6 +93,8 @@ static struct pmbus_driver_info max16064_info = {
.func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
.func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
.func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
.read_word_data = max16064_read_word_data,
.write_word_data = max16064_write_word_data,
}; };
static int max16064_probe(struct i2c_client *client, static int max16064_probe(struct i2c_client *client,
......
...@@ -27,11 +27,70 @@ ...@@ -27,11 +27,70 @@
enum chips { max34440, max34441 }; enum chips { max34440, max34441 };
#define MAX34440_MFR_VOUT_PEAK 0xd4
#define MAX34440_MFR_IOUT_PEAK 0xd5
#define MAX34440_MFR_TEMPERATURE_PEAK 0xd6
#define MAX34440_STATUS_OC_WARN (1 << 0) #define MAX34440_STATUS_OC_WARN (1 << 0)
#define MAX34440_STATUS_OC_FAULT (1 << 1) #define MAX34440_STATUS_OC_FAULT (1 << 1)
#define MAX34440_STATUS_OT_FAULT (1 << 5) #define MAX34440_STATUS_OT_FAULT (1 << 5)
#define MAX34440_STATUS_OT_WARN (1 << 6) #define MAX34440_STATUS_OT_WARN (1 << 6)
static int max34440_read_word_data(struct i2c_client *client, int page, int reg)
{
int ret;
switch (reg) {
case PMBUS_VIRT_READ_VOUT_MAX:
ret = pmbus_read_word_data(client, page,
MAX34440_MFR_VOUT_PEAK);
break;
case PMBUS_VIRT_READ_IOUT_MAX:
ret = pmbus_read_word_data(client, page,
MAX34440_MFR_IOUT_PEAK);
break;
case PMBUS_VIRT_READ_TEMP_MAX:
ret = pmbus_read_word_data(client, page,
MAX34440_MFR_TEMPERATURE_PEAK);
break;
case PMBUS_VIRT_RESET_VOUT_HISTORY:
case PMBUS_VIRT_RESET_IOUT_HISTORY:
case PMBUS_VIRT_RESET_TEMP_HISTORY:
ret = 0;
break;
default:
ret = -ENODATA;
break;
}
return ret;
}
static int max34440_write_word_data(struct i2c_client *client, int page,
int reg, u16 word)
{
int ret;
switch (reg) {
case PMBUS_VIRT_RESET_VOUT_HISTORY:
ret = pmbus_write_word_data(client, page,
MAX34440_MFR_VOUT_PEAK, 0);
break;
case PMBUS_VIRT_RESET_IOUT_HISTORY:
ret = pmbus_write_word_data(client, page,
MAX34440_MFR_IOUT_PEAK, 0);
break;
case PMBUS_VIRT_RESET_TEMP_HISTORY:
ret = pmbus_write_word_data(client, page,
MAX34440_MFR_TEMPERATURE_PEAK,
0xffff);
break;
default:
ret = -ENODATA;
break;
}
return ret;
}
static int max34440_read_byte_data(struct i2c_client *client, int page, int reg) static int max34440_read_byte_data(struct i2c_client *client, int page, int reg)
{ {
int ret; int ret;
...@@ -72,10 +131,10 @@ static int max34440_read_byte_data(struct i2c_client *client, int page, int reg) ...@@ -72,10 +131,10 @@ static int max34440_read_byte_data(struct i2c_client *client, int page, int reg)
static struct pmbus_driver_info max34440_info[] = { static struct pmbus_driver_info max34440_info[] = {
[max34440] = { [max34440] = {
.pages = 14, .pages = 14,
.direct[PSC_VOLTAGE_IN] = true, .format[PSC_VOLTAGE_IN] = direct,
.direct[PSC_VOLTAGE_OUT] = true, .format[PSC_VOLTAGE_OUT] = direct,
.direct[PSC_TEMPERATURE] = true, .format[PSC_TEMPERATURE] = direct,
.direct[PSC_CURRENT_OUT] = true, .format[PSC_CURRENT_OUT] = direct,
.m[PSC_VOLTAGE_IN] = 1, .m[PSC_VOLTAGE_IN] = 1,
.b[PSC_VOLTAGE_IN] = 0, .b[PSC_VOLTAGE_IN] = 0,
.R[PSC_VOLTAGE_IN] = 3, /* R = 0 in datasheet reflects mV */ .R[PSC_VOLTAGE_IN] = 3, /* R = 0 in datasheet reflects mV */
...@@ -109,14 +168,16 @@ static struct pmbus_driver_info max34440_info[] = { ...@@ -109,14 +168,16 @@ static struct pmbus_driver_info max34440_info[] = {
.func[12] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, .func[12] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
.func[13] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, .func[13] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
.read_byte_data = max34440_read_byte_data, .read_byte_data = max34440_read_byte_data,
.read_word_data = max34440_read_word_data,
.write_word_data = max34440_write_word_data,
}, },
[max34441] = { [max34441] = {
.pages = 12, .pages = 12,
.direct[PSC_VOLTAGE_IN] = true, .format[PSC_VOLTAGE_IN] = direct,
.direct[PSC_VOLTAGE_OUT] = true, .format[PSC_VOLTAGE_OUT] = direct,
.direct[PSC_TEMPERATURE] = true, .format[PSC_TEMPERATURE] = direct,
.direct[PSC_CURRENT_OUT] = true, .format[PSC_CURRENT_OUT] = direct,
.direct[PSC_FAN] = true, .format[PSC_FAN] = direct,
.m[PSC_VOLTAGE_IN] = 1, .m[PSC_VOLTAGE_IN] = 1,
.b[PSC_VOLTAGE_IN] = 0, .b[PSC_VOLTAGE_IN] = 0,
.R[PSC_VOLTAGE_IN] = 3, .R[PSC_VOLTAGE_IN] = 3,
...@@ -150,6 +211,8 @@ static struct pmbus_driver_info max34440_info[] = { ...@@ -150,6 +211,8 @@ static struct pmbus_driver_info max34440_info[] = {
.func[10] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, .func[10] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
.func[11] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, .func[11] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
.read_byte_data = max34440_read_byte_data, .read_byte_data = max34440_read_byte_data,
.read_word_data = max34440_read_word_data,
.write_word_data = max34440_write_word_data,
}, },
}; };
......
...@@ -25,6 +25,9 @@ ...@@ -25,6 +25,9 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include "pmbus.h" #include "pmbus.h"
#define MAX8688_MFR_VOUT_PEAK 0xd4
#define MAX8688_MFR_IOUT_PEAK 0xd5
#define MAX8688_MFR_TEMPERATURE_PEAK 0xd6
#define MAX8688_MFG_STATUS 0xd8 #define MAX8688_MFG_STATUS 0xd8
#define MAX8688_STATUS_OC_FAULT (1 << 4) #define MAX8688_STATUS_OC_FAULT (1 << 4)
...@@ -37,6 +40,62 @@ ...@@ -37,6 +40,62 @@
#define MAX8688_STATUS_OT_FAULT (1 << 13) #define MAX8688_STATUS_OT_FAULT (1 << 13)
#define MAX8688_STATUS_OT_WARNING (1 << 14) #define MAX8688_STATUS_OT_WARNING (1 << 14)
static int max8688_read_word_data(struct i2c_client *client, int page, int reg)
{
int ret;
if (page)
return -EINVAL;
switch (reg) {
case PMBUS_VIRT_READ_VOUT_MAX:
ret = pmbus_read_word_data(client, 0, MAX8688_MFR_VOUT_PEAK);
break;
case PMBUS_VIRT_READ_IOUT_MAX:
ret = pmbus_read_word_data(client, 0, MAX8688_MFR_IOUT_PEAK);
break;
case PMBUS_VIRT_READ_TEMP_MAX:
ret = pmbus_read_word_data(client, 0,
MAX8688_MFR_TEMPERATURE_PEAK);
break;
case PMBUS_VIRT_RESET_VOUT_HISTORY:
case PMBUS_VIRT_RESET_IOUT_HISTORY:
case PMBUS_VIRT_RESET_TEMP_HISTORY:
ret = 0;
break;
default:
ret = -ENODATA;
break;
}
return ret;
}
static int max8688_write_word_data(struct i2c_client *client, int page, int reg,
u16 word)
{
int ret;
switch (reg) {
case PMBUS_VIRT_RESET_VOUT_HISTORY:
ret = pmbus_write_word_data(client, 0, MAX8688_MFR_VOUT_PEAK,
0);
break;
case PMBUS_VIRT_RESET_IOUT_HISTORY:
ret = pmbus_write_word_data(client, 0, MAX8688_MFR_IOUT_PEAK,
0);
break;
case PMBUS_VIRT_RESET_TEMP_HISTORY:
ret = pmbus_write_word_data(client, 0,
MAX8688_MFR_TEMPERATURE_PEAK,
0xffff);
break;
default:
ret = -ENODATA;
break;
}
return ret;
}
static int max8688_read_byte_data(struct i2c_client *client, int page, int reg) static int max8688_read_byte_data(struct i2c_client *client, int page, int reg)
{ {
int ret = 0; int ret = 0;
...@@ -91,10 +150,10 @@ static int max8688_read_byte_data(struct i2c_client *client, int page, int reg) ...@@ -91,10 +150,10 @@ static int max8688_read_byte_data(struct i2c_client *client, int page, int reg)
static struct pmbus_driver_info max8688_info = { static struct pmbus_driver_info max8688_info = {
.pages = 1, .pages = 1,
.direct[PSC_VOLTAGE_IN] = true, .format[PSC_VOLTAGE_IN] = direct,
.direct[PSC_VOLTAGE_OUT] = true, .format[PSC_VOLTAGE_OUT] = direct,
.direct[PSC_TEMPERATURE] = true, .format[PSC_TEMPERATURE] = direct,
.direct[PSC_CURRENT_OUT] = true, .format[PSC_CURRENT_OUT] = direct,
.m[PSC_VOLTAGE_IN] = 19995, .m[PSC_VOLTAGE_IN] = 19995,
.b[PSC_VOLTAGE_IN] = 0, .b[PSC_VOLTAGE_IN] = 0,
.R[PSC_VOLTAGE_IN] = -1, .R[PSC_VOLTAGE_IN] = -1,
...@@ -111,6 +170,8 @@ static struct pmbus_driver_info max8688_info = { ...@@ -111,6 +170,8 @@ static struct pmbus_driver_info max8688_info = {
| PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT
| PMBUS_HAVE_STATUS_TEMP, | PMBUS_HAVE_STATUS_TEMP,
.read_byte_data = max8688_read_byte_data, .read_byte_data = max8688_read_byte_data,
.read_word_data = max8688_read_word_data,
.write_word_data = max8688_write_word_data,
}; };
static int max8688_probe(struct i2c_client *client, static int max8688_probe(struct i2c_client *client,
......
...@@ -96,6 +96,8 @@ static void pmbus_find_sensor_groups(struct i2c_client *client, ...@@ -96,6 +96,8 @@ static void pmbus_find_sensor_groups(struct i2c_client *client,
static int pmbus_identify(struct i2c_client *client, static int pmbus_identify(struct i2c_client *client,
struct pmbus_driver_info *info) struct pmbus_driver_info *info)
{ {
int ret = 0;
if (!info->pages) { if (!info->pages) {
/* /*
* Check if the PAGE command is supported. If it is, * Check if the PAGE command is supported. If it is,
...@@ -117,6 +119,27 @@ static int pmbus_identify(struct i2c_client *client, ...@@ -117,6 +119,27 @@ static int pmbus_identify(struct i2c_client *client,
} }
} }
if (pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE)) {
int vout_mode;
vout_mode = pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE);
if (vout_mode >= 0 && vout_mode != 0xff) {
switch (vout_mode >> 5) {
case 0:
break;
case 1:
info->format[PSC_VOLTAGE_OUT] = vid;
break;
case 2:
info->format[PSC_VOLTAGE_OUT] = direct;
break;
default:
ret = -ENODEV;
goto abort;
}
}
}
/* /*
* We should check if the COEFFICIENTS register is supported. * We should check if the COEFFICIENTS register is supported.
* If it is, and the chip is configured for direct mode, we can read * If it is, and the chip is configured for direct mode, we can read
...@@ -125,13 +148,18 @@ static int pmbus_identify(struct i2c_client *client, ...@@ -125,13 +148,18 @@ static int pmbus_identify(struct i2c_client *client,
* *
* To do this, we will need access to a chip which actually supports the * To do this, we will need access to a chip which actually supports the
* COEFFICIENTS command, since the command is too complex to implement * COEFFICIENTS command, since the command is too complex to implement
* without testing it. * without testing it. Until then, abort if a chip configured for direct
* mode was detected.
*/ */
if (info->format[PSC_VOLTAGE_OUT] == direct) {
ret = -ENODEV;
goto abort;
}
/* Try to find sensor groups */ /* Try to find sensor groups */
pmbus_find_sensor_groups(client, info); pmbus_find_sensor_groups(client, info);
abort:
return 0; return ret;
} }
static int pmbus_probe(struct i2c_client *client, static int pmbus_probe(struct i2c_client *client,
...@@ -172,11 +200,14 @@ static int pmbus_remove(struct i2c_client *client) ...@@ -172,11 +200,14 @@ static int pmbus_remove(struct i2c_client *client)
* Use driver_data to set the number of pages supported by the chip. * Use driver_data to set the number of pages supported by the chip.
*/ */
static const struct i2c_device_id pmbus_id[] = { static const struct i2c_device_id pmbus_id[] = {
{"adp4000", 1},
{"bmr450", 1}, {"bmr450", 1},
{"bmr451", 1}, {"bmr451", 1},
{"bmr453", 1}, {"bmr453", 1},
{"bmr454", 1}, {"bmr454", 1},
{"ltc2978", 8}, {"ltc2978", 8},
{"ncp4200", 1},
{"ncp4208", 1},
{"pmbus", 0}, {"pmbus", 0},
{} {}
}; };
......
...@@ -125,6 +125,42 @@ ...@@ -125,6 +125,42 @@
#define PMBUS_MFR_DATE 0x9D #define PMBUS_MFR_DATE 0x9D
#define PMBUS_MFR_SERIAL 0x9E #define PMBUS_MFR_SERIAL 0x9E
/*
* Virtual registers.
* Useful to support attributes which are not supported by standard PMBus
* registers but exist as manufacturer specific registers on individual chips.
* Must be mapped to real registers in device specific code.
*
* Semantics:
* Virtual registers are all word size.
* READ registers are read-only; writes are either ignored or return an error.
* RESET registers are read/write. Reading returns zero (used for detection),
* writing any value causes the associated history to be reset.
*/
#define PMBUS_VIRT_BASE 0x100
#define PMBUS_VIRT_READ_TEMP_MIN (PMBUS_VIRT_BASE + 0)
#define PMBUS_VIRT_READ_TEMP_MAX (PMBUS_VIRT_BASE + 1)
#define PMBUS_VIRT_RESET_TEMP_HISTORY (PMBUS_VIRT_BASE + 2)
#define PMBUS_VIRT_READ_VIN_AVG (PMBUS_VIRT_BASE + 3)
#define PMBUS_VIRT_READ_VIN_MIN (PMBUS_VIRT_BASE + 4)
#define PMBUS_VIRT_READ_VIN_MAX (PMBUS_VIRT_BASE + 5)
#define PMBUS_VIRT_RESET_VIN_HISTORY (PMBUS_VIRT_BASE + 6)
#define PMBUS_VIRT_READ_IIN_AVG (PMBUS_VIRT_BASE + 7)
#define PMBUS_VIRT_READ_IIN_MIN (PMBUS_VIRT_BASE + 8)
#define PMBUS_VIRT_READ_IIN_MAX (PMBUS_VIRT_BASE + 9)
#define PMBUS_VIRT_RESET_IIN_HISTORY (PMBUS_VIRT_BASE + 10)
#define PMBUS_VIRT_READ_PIN_AVG (PMBUS_VIRT_BASE + 11)
#define PMBUS_VIRT_READ_PIN_MAX (PMBUS_VIRT_BASE + 12)
#define PMBUS_VIRT_RESET_PIN_HISTORY (PMBUS_VIRT_BASE + 13)
#define PMBUS_VIRT_READ_VOUT_AVG (PMBUS_VIRT_BASE + 14)
#define PMBUS_VIRT_READ_VOUT_MIN (PMBUS_VIRT_BASE + 15)
#define PMBUS_VIRT_READ_VOUT_MAX (PMBUS_VIRT_BASE + 16)
#define PMBUS_VIRT_RESET_VOUT_HISTORY (PMBUS_VIRT_BASE + 17)
#define PMBUS_VIRT_READ_IOUT_AVG (PMBUS_VIRT_BASE + 18)
#define PMBUS_VIRT_READ_IOUT_MIN (PMBUS_VIRT_BASE + 19)
#define PMBUS_VIRT_READ_IOUT_MAX (PMBUS_VIRT_BASE + 20)
#define PMBUS_VIRT_RESET_IOUT_HISTORY (PMBUS_VIRT_BASE + 21)
/* /*
* CAPABILITY * CAPABILITY
*/ */
...@@ -266,11 +302,11 @@ enum pmbus_sensor_classes { ...@@ -266,11 +302,11 @@ enum pmbus_sensor_classes {
#define PMBUS_HAVE_STATUS_FAN12 (1 << 16) #define PMBUS_HAVE_STATUS_FAN12 (1 << 16)
#define PMBUS_HAVE_STATUS_FAN34 (1 << 17) #define PMBUS_HAVE_STATUS_FAN34 (1 << 17)
enum pmbus_data_format { linear = 0, direct, vid };
struct pmbus_driver_info { struct pmbus_driver_info {
int pages; /* Total number of pages */ int pages; /* Total number of pages */
bool direct[PSC_NUM_CLASSES]; enum pmbus_data_format format[PSC_NUM_CLASSES];
/* true if device uses direct data format
for the given sensor class */
/* /*
* Support one set of coefficients for each sensor type * Support one set of coefficients for each sensor type
* Used for chips providing data in direct mode. * Used for chips providing data in direct mode.
...@@ -286,6 +322,9 @@ struct pmbus_driver_info { ...@@ -286,6 +322,9 @@ struct pmbus_driver_info {
* necessary. * necessary.
*/ */
int (*read_byte_data)(struct i2c_client *client, int page, int reg); int (*read_byte_data)(struct i2c_client *client, int page, int reg);
int (*read_word_data)(struct i2c_client *client, int page, int reg);
int (*write_word_data)(struct i2c_client *client, int page, int reg,
u16 word);
/* /*
* The identify function determines supported PMBus functionality. * The identify function determines supported PMBus functionality.
* This function is only necessary if a chip driver supports multiple * This function is only necessary if a chip driver supports multiple
...@@ -299,6 +338,9 @@ struct pmbus_driver_info { ...@@ -299,6 +338,9 @@ struct pmbus_driver_info {
int pmbus_set_page(struct i2c_client *client, u8 page); int pmbus_set_page(struct i2c_client *client, u8 page);
int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg); int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg);
int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word);
int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg);
int pmbus_write_byte(struct i2c_client *client, int page, u8 value);
void pmbus_clear_faults(struct i2c_client *client); void pmbus_clear_faults(struct i2c_client *client);
bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg); bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg);
bool pmbus_check_word_register(struct i2c_client *client, int page, int reg); bool pmbus_check_word_register(struct i2c_client *client, int page, int reg);
......
/*
* ntc_thermistor.h - NTC Thermistors
*
* Copyright (C) 2010 Samsung Electronics
* MyungJoo Ham <myungjoo.ham@samsung.com>
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _LINUX_NTC_H
#define _LINUX_NTC_H
enum ntc_thermistor_type {
TYPE_NCPXXWB473,
TYPE_NCPXXWL333,
};
struct ntc_thermistor_platform_data {
/*
* One (not both) of read_uV and read_ohm should be provided and only
* one of the two should be provided.
* Both functions should return negative value for an error case.
*
* pullup_uV, pullup_ohm, pulldown_ohm, and connect are required to use
* read_uV()
*
* How to setup pullup_ohm, pulldown_ohm, and connect is
* described at Documentation/hwmon/ntc
*
* pullup/down_ohm: 0 for infinite / not-connected
*/
int (*read_uV)(void);
unsigned int pullup_uV;
unsigned int pullup_ohm;
unsigned int pulldown_ohm;
enum { NTC_CONNECTED_POSITIVE, NTC_CONNECTED_GROUND } connect;
int (*read_ohm)(void);
};
#endif /* _LINUX_NTC_H */
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