Commit 19520fc1 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: (44 commits)
  hwmon: (lineage-pem): Fix in1 voltage alarm sysfs attributes
  hwmon/f71882fg: Add support for f71808e
  hwmon/f71882fg: Add support for f71869f and f71869e
  hwmon/f71882fg: Add support for f71889ed
  hwmon/f71882fg: Break out test for auto pwm's controlled by digital readings
  hwmon/f71882fg: Separate temp beep sysfs attr from the other temp sysfs attr
  hwmon/f71882fg: Remove bogus temp2_type for certain models
  hwmon/f71882fg: Make number of temps configurable
  hwmon/f71882fg: Make creation of in sysfs attributes more generic
  hwmon/f71882fg: Only allow negative auto point temps if fan_neg_temp is enabled
  hwmon/f71882fg: Fix temp1 sensor type reporting
  hwmon: (w83627ehf) Display correct temperature sensor labels for systems with NCT6775F
  hwmon: (w83627ehf) Add fan debounce support for NCT6775F and NCT6776F
  hwmon: (w83627ehf) Update Kconfig for W83677HG-B, NCT6775F and NCT6776F
  hwmon: (w83627ehf) Store rpm instead of raw fan speed data
  hwmon: (w83627ehf) Use 16 bit fan count registers if supported
  hwmon: (w83627ehf) Add support for Nuvoton NCT6775F and NCT6776F
  hwmon: (w83627ehf) Permit enabling SmartFan IV mode if configured at startup
  hwmon: (w83627ehf) Convert register arrays to 16 bit, and convert access to pointers
  hwmon: (w83627ehf) Remove references to datasheets which no longer exist
  ...
parents c8def554 d668a8b0
...@@ -10,6 +10,10 @@ Supported chips: ...@@ -10,6 +10,10 @@ Supported chips:
Prefix: 'f71862fg' Prefix: 'f71862fg'
Addresses scanned: none, address read from Super I/O config space Addresses scanned: none, address read from Super I/O config space
Datasheet: Available from the Fintek website Datasheet: Available from the Fintek website
* Fintek F71869F and F71869E
Prefix: 'f71869'
Addresses scanned: none, address read from Super I/O config space
Datasheet: Available from the Fintek website
* Fintek F71882FG and F71883FG * Fintek F71882FG and F71883FG
Prefix: 'f71882fg' Prefix: 'f71882fg'
Addresses scanned: none, address read from Super I/O config space Addresses scanned: none, address read from Super I/O config space
...@@ -17,6 +21,10 @@ Supported chips: ...@@ -17,6 +21,10 @@ Supported chips:
* Fintek F71889FG * Fintek F71889FG
Prefix: 'f71889fg' Prefix: 'f71889fg'
Addresses scanned: none, address read from Super I/O config space Addresses scanned: none, address read from Super I/O config space
Datasheet: Available from the Fintek website
* Fintek F71889ED
Prefix: 'f71889ed'
Addresses scanned: none, address read from Super I/O config space
Datasheet: Should become available on the Fintek website soon Datasheet: Should become available on the Fintek website soon
* Fintek F8000 * Fintek F8000
Prefix: 'f8000' Prefix: 'f8000'
...@@ -29,9 +37,9 @@ Author: Hans de Goede <hdegoede@redhat.com> ...@@ -29,9 +37,9 @@ Author: Hans de Goede <hdegoede@redhat.com>
Description Description
----------- -----------
Fintek F718xxFG/F8000 Super I/O chips include complete hardware monitoring Fintek F718xx/F8000 Super I/O chips include complete hardware monitoring
capabilities. They can monitor up to 9 voltages (3 for the F8000), 4 fans and capabilities. They can monitor up to 9 voltages, 4 fans and 3 temperature
3 temperature sensors. sensors.
These chips also have fan controlling features, using either DC or PWM, in These chips also have fan controlling features, using either DC or PWM, in
three different modes (one manual, two automatic). three different modes (one manual, two automatic).
...@@ -99,5 +107,5 @@ Writing an unsupported mode will result in an invalid parameter error. ...@@ -99,5 +107,5 @@ Writing an unsupported mode will result in an invalid parameter error.
The fan speed is regulated to keep the temp the fan is mapped to between The fan speed is regulated to keep the temp the fan is mapped to between
temp#_auto_point2_temp and temp#_auto_point3_temp. temp#_auto_point2_temp and temp#_auto_point3_temp.
Both of the automatic modes require that pwm1 corresponds to fan1, pwm2 to All of the automatic modes require that pwm1 corresponds to fan1, pwm2 to
fan2 and pwm3 to fan3. fan2 and pwm3 to fan3.
Kernel driver lineage-pem
=========================
Supported devices:
* Lineage Compact Power Line Power Entry Modules
Prefix: 'lineage-pem'
Addresses scanned: -
Documentation:
http://www.lineagepower.com/oem/pdf/CPLI2C.pdf
Author: Guenter Roeck <guenter.roeck@ericsson.com>
Description
-----------
This driver supports various Lineage Compact Power Line DC/DC and AC/DC
converters such as CP1800, CP2000AC, CP2000DC, CP2100DC, and others.
Lineage CPL power entry modules are nominally PMBus compliant. However, most
standard PMBus commands are not supported. Specifically, all hardware monitoring
and status reporting commands are non-standard. For this reason, a standard
PMBus driver can not be used.
Usage Notes
-----------
This driver does not probe for Lineage CPL devices, since there is no register
which can be safely used to identify the chip. You will have to instantiate
the devices explicitly.
Example: the following will load the driver for a Lineage PEM at address 0x40
on I2C bus #1:
$ modprobe lineage-pem
$ echo lineage-pem 0x40 > /sys/bus/i2c/devices/i2c-1/new_device
All Lineage CPL power entry modules have a built-in I2C bus master selector
(PCA9541). To ensure device access, this driver should only be used as client
driver to the pca9541 I2C master selector driver.
Sysfs entries
-------------
All Lineage CPL devices report output voltage and device temperature as well as
alarms for output voltage, temperature, input voltage, input current, input power,
and fan status.
Input voltage, input current, input power, and fan speed measurement is only
supported on newer devices. The driver detects if those attributes are supported,
and only creates respective sysfs entries if they are.
in1_input Output voltage (mV)
in1_min_alarm Output undervoltage alarm
in1_max_alarm Output overvoltage alarm
in1_crit Output voltage critical alarm
in2_input Input voltage (mV, optional)
in2_alarm Input voltage alarm
curr1_input Input current (mA, optional)
curr1_alarm Input overcurrent alarm
power1_input Input power (uW, optional)
power1_alarm Input power alarm
fan1_input Fan 1 speed (rpm, optional)
fan2_input Fan 2 speed (rpm, optional)
fan3_input Fan 3 speed (rpm, optional)
temp1_input
temp1_max
temp1_crit
temp1_alarm
temp1_crit_alarm
temp1_fault
...@@ -26,6 +26,14 @@ Supported chips: ...@@ -26,6 +26,14 @@ Supported chips:
Prefix: 'emc6d102' Prefix: 'emc6d102'
Addresses scanned: I2C 0x2c, 0x2d, 0x2e Addresses scanned: I2C 0x2c, 0x2d, 0x2e
Datasheet: http://www.smsc.com/main/catalog/emc6d102.html Datasheet: http://www.smsc.com/main/catalog/emc6d102.html
* SMSC EMC6D103
Prefix: 'emc6d103'
Addresses scanned: I2C 0x2c, 0x2d, 0x2e
Datasheet: http://www.smsc.com/main/catalog/emc6d103.html
* SMSC EMC6D103S
Prefix: 'emc6d103s'
Addresses scanned: I2C 0x2c, 0x2d, 0x2e
Datasheet: http://www.smsc.com/main/catalog/emc6d103s.html
Authors: Authors:
Philip Pokorny <ppokorny@penguincomputing.com>, Philip Pokorny <ppokorny@penguincomputing.com>,
...@@ -122,9 +130,11 @@ to be register compatible. The EMC6D100 offers all the features of the ...@@ -122,9 +130,11 @@ to be register compatible. The EMC6D100 offers all the features of the
EMC6D101 plus additional voltage monitoring and system control features. EMC6D101 plus additional voltage monitoring and system control features.
Unfortunately it is not possible to distinguish between the package Unfortunately it is not possible to distinguish between the package
versions on register level so these additional voltage inputs may read versions on register level so these additional voltage inputs may read
zero. The EMC6D102 features addtional ADC bits thus extending precision zero. EMC6D102 and EMC6D103 feature additional ADC bits thus extending precision
of voltage and temperature channels. of voltage and temperature channels.
SMSC EMC6D103S is similar to EMC6D103, but does not support pwm#_auto_pwm_minctl
and temp#_auto_temp_off.
Hardware Configurations Hardware Configurations
----------------------- -----------------------
......
Kernel driver ltc4151
=====================
Supported chips:
* Linear Technology LTC4151
Prefix: 'ltc4151'
Addresses scanned: -
Datasheet:
http://www.linear.com/docs/Datasheet/4151fc.pdf
Author: Per Dalen <per.dalen@appeartv.com>
Description
-----------
The LTC4151 is a High Voltage I2C Current and Voltage Monitor.
Usage Notes
-----------
This driver does not probe for LTC4151 devices, since there is no register
which can be safely used to identify the chip. You will have to instantiate
the devices explicitly.
Example: the following will load the driver for an LTC4151 at address 0x6f
on I2C bus #0:
# modprobe ltc4151
# echo ltc4151 0x6f > /sys/bus/i2c/devices/i2c-0/new_device
Sysfs entries
-------------
Voltage readings provided by this driver are reported as obtained from the ADIN
and VIN registers.
Current reading provided by this driver is reported as obtained from the Current
Sense register. The reported value assumes that a 1 mOhm sense resistor is
installed.
in1_input VDIN voltage (mV)
in2_input ADIN voltage (mV)
curr1_input SENSE current (mA)
Kernel driver max6639
=====================
Supported chips:
* Maxim MAX6639
Prefix: 'max6639'
Addresses scanned: I2C 0x2c, 0x2e, 0x2f
Datasheet: http://pdfserv.maxim-ic.com/en/ds/MAX6639.pdf
Authors:
He Changqing <hechangqing@semptian.com>
Roland Stigge <stigge@antcom.de>
Description
-----------
This driver implements support for the Maxim MAX6639. This chip is a 2-channel
temperature monitor with dual PWM fan speed controller. It can monitor its own
temperature and one external diode-connected transistor or two external
diode-connected transistors.
The following device attributes are implemented via sysfs:
Attribute R/W Contents
----------------------------------------------------------------------------
temp1_input R Temperature channel 1 input (0..150 C)
temp2_input R Temperature channel 2 input (0..150 C)
temp1_fault R Temperature channel 1 diode fault
temp2_fault R Temperature channel 2 diode fault
temp1_max RW Set THERM temperature for input 1
(in C, see datasheet)
temp2_max RW Set THERM temperature for input 2
temp1_crit RW Set ALERT temperature for input 1
temp2_crit RW Set ALERT temperature for input 2
temp1_emergency RW Set OT temperature for input 1
(in C, see datasheet)
temp2_emergency RW Set OT temperature for input 2
pwm1 RW Fan 1 target duty cycle (0..255)
pwm2 RW Fan 2 target duty cycle (0..255)
fan1_input R TACH1 fan tachometer input (in RPM)
fan2_input R TACH2 fan tachometer input (in RPM)
fan1_fault R Fan 1 fault
fan2_fault R Fan 2 fault
temp1_max_alarm R Alarm on THERM temperature on channel 1
temp2_max_alarm R Alarm on THERM temperature on channel 2
temp1_crit_alarm R Alarm on ALERT temperature on channel 1
temp2_crit_alarm R Alarm on ALERT temperature on channel 2
temp1_emergency_alarm R Alarm on OT temperature on channel 1
temp2_emergency_alarm R Alarm on OT temperature on channel 2
Kernel driver pmbus
====================
Supported chips:
* Ericsson BMR45X series
DC/DC Converter
Prefixes: 'bmr450', 'bmr451', 'bmr453', 'bmr454'
Addresses scanned: -
Datasheet:
http://archive.ericsson.net/service/internet/picov/get?DocNo=28701-EN/LZT146395
* Linear Technology LTC2978
Octal PMBus Power Supply Monitor and Controller
Prefix: 'ltc2978'
Addresses scanned: -
Datasheet: http://cds.linear.com/docs/Datasheet/2978fa.pdf
* Maxim MAX16064
Quad Power-Supply Controller
Prefix: 'max16064'
Addresses scanned: -
Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX16064.pdf
* Maxim MAX34440
PMBus 6-Channel Power-Supply Manager
Prefixes: 'max34440'
Addresses scanned: -
Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX34440.pdf
* Maxim MAX34441
PMBus 5-Channel Power-Supply Manager and Intelligent Fan Controller
Prefixes: 'max34441'
Addresses scanned: -
Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX34441.pdf
* Maxim MAX8688
Digital Power-Supply Controller/Monitor
Prefix: 'max8688'
Addresses scanned: -
Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX8688.pdf
* Generic PMBus devices
Prefix: 'pmbus'
Addresses scanned: -
Datasheet: n.a.
Author: Guenter Roeck <guenter.roeck@ericsson.com>
Description
-----------
This driver supports hardware montoring for various PMBus compliant devices.
It supports voltage, current, power, and temperature sensors as supported
by the device.
Each monitored channel has its own high and low limits, plus a critical
limit.
Fan support will be added in a later version of this driver.
Usage Notes
-----------
This driver does not probe for PMBus devices, since there is no register
which can be safely used to identify the chip (The MFG_ID register is not
supported by all chips), and since there is no well defined address range for
PMBus devices. You will have to instantiate the devices explicitly.
Example: the following will load the driver for an LTC2978 at address 0x60
on I2C bus #1:
$ modprobe pmbus
$ echo ltc2978 0x60 > /sys/bus/i2c/devices/i2c-1/new_device
Platform data support
---------------------
Support for additional PMBus chips can be added by defining chip parameters in
a new chip specific driver file. For example, (untested) code to add support for
Emerson DS1200 power modules might look as follows.
static struct pmbus_driver_info ds1200_info = {
.pages = 1,
/* Note: All other sensors are in linear mode */
.direct[PSC_VOLTAGE_OUT] = true,
.direct[PSC_TEMPERATURE] = true,
.direct[PSC_CURRENT_OUT] = true,
.m[PSC_VOLTAGE_IN] = 1,
.b[PSC_VOLTAGE_IN] = 0,
.R[PSC_VOLTAGE_IN] = 3,
.m[PSC_VOLTAGE_OUT] = 1,
.b[PSC_VOLTAGE_OUT] = 0,
.R[PSC_VOLTAGE_OUT] = 3,
.m[PSC_TEMPERATURE] = 1,
.b[PSC_TEMPERATURE] = 0,
.R[PSC_TEMPERATURE] = 3,
.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_STATUS_TEMP
| PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12,
};
static int ds1200_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
return pmbus_do_probe(client, id, &ds1200_info);
}
static int ds1200_remove(struct i2c_client *client)
{
return pmbus_do_remove(client);
}
static const struct i2c_device_id ds1200_id[] = {
{"ds1200", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, ds1200_id);
/* This is the driver that will be inserted */
static struct i2c_driver ds1200_driver = {
.driver = {
.name = "ds1200",
},
.probe = ds1200_probe,
.remove = ds1200_remove,
.id_table = ds1200_id,
};
static int __init ds1200_init(void)
{
return i2c_add_driver(&ds1200_driver);
}
static void __exit ds1200_exit(void)
{
i2c_del_driver(&ds1200_driver);
}
Sysfs entries
-------------
When probing the chip, the driver identifies which PMBus registers are
supported, and determines available sensors from this information.
Attribute files only exist if respective sensors are suported by the chip.
Labels are provided to inform the user about the sensor associated with
a given sysfs entry.
The following attributes are supported. Limits are read-write; all other
attributes are read-only.
inX_input Measured voltage. From READ_VIN or READ_VOUT register.
inX_min Minumum Voltage.
From VIN_UV_WARN_LIMIT or VOUT_UV_WARN_LIMIT register.
inX_max Maximum voltage.
From VIN_OV_WARN_LIMIT or VOUT_OV_WARN_LIMIT register.
inX_lcrit Critical minumum Voltage.
From VIN_UV_FAULT_LIMIT or VOUT_UV_FAULT_LIMIT register.
inX_crit Critical maximum voltage.
From VIN_OV_FAULT_LIMIT or VOUT_OV_FAULT_LIMIT register.
inX_min_alarm Voltage low alarm. From VOLTAGE_UV_WARNING status.
inX_max_alarm Voltage high alarm. From VOLTAGE_OV_WARNING status.
inX_lcrit_alarm Voltage critical low alarm.
From VOLTAGE_UV_FAULT status.
inX_crit_alarm Voltage critical high alarm.
From VOLTAGE_OV_FAULT status.
inX_label "vin", "vcap", or "voutY"
currX_input Measured current. From READ_IIN or READ_IOUT register.
currX_max Maximum current.
From IIN_OC_WARN_LIMIT or IOUT_OC_WARN_LIMIT register.
currX_lcrit Critical minumum output current.
From IOUT_UC_FAULT_LIMIT register.
currX_crit Critical maximum current.
From IIN_OC_FAULT_LIMIT or IOUT_OC_FAULT_LIMIT register.
currX_alarm Current high alarm.
From IIN_OC_WARNING or IOUT_OC_WARNING status.
currX_lcrit_alarm Output current critical low alarm.
From IOUT_UC_FAULT status.
currX_crit_alarm Current critical high alarm.
From IIN_OC_FAULT or IOUT_OC_FAULT status.
currX_label "iin" or "vinY"
powerX_input Measured power. From READ_PIN or READ_POUT register.
powerX_cap Output power cap. From POUT_MAX register.
powerX_max Power limit. From PIN_OP_WARN_LIMIT or
POUT_OP_WARN_LIMIT register.
powerX_crit Critical output power limit.
From POUT_OP_FAULT_LIMIT register.
powerX_alarm Power high alarm.
From PIN_OP_WARNING or POUT_OP_WARNING status.
powerX_crit_alarm Output power critical high alarm.
From POUT_OP_FAULT status.
powerX_label "pin" or "poutY"
tempX_input Measured tempererature.
From READ_TEMPERATURE_X register.
tempX_min Mimimum tempererature. From UT_WARN_LIMIT register.
tempX_max Maximum tempererature. From OT_WARN_LIMIT register.
tempX_lcrit Critical low tempererature.
From UT_FAULT_LIMIT register.
tempX_crit Critical high tempererature.
From OT_FAULT_LIMIT register.
tempX_min_alarm Chip temperature low alarm. Set by comparing
READ_TEMPERATURE_X with UT_WARN_LIMIT if
TEMP_UT_WARNING status is set.
tempX_max_alarm Chip temperature high alarm. Set by comparing
READ_TEMPERATURE_X with OT_WARN_LIMIT if
TEMP_OT_WARNING status is set.
tempX_lcrit_alarm Chip temperature critical low alarm. Set by comparing
READ_TEMPERATURE_X with UT_FAULT_LIMIT if
TEMP_UT_FAULT status is set.
tempX_crit_alarm Chip temperature critical high alarm. Set by comparing
READ_TEMPERATURE_X with OT_FAULT_LIMIT if
TEMP_OT_FAULT status is set.
...@@ -187,6 +187,17 @@ fan[1-*]_div Fan divisor. ...@@ -187,6 +187,17 @@ fan[1-*]_div Fan divisor.
Note that this is actually an internal clock divisor, which Note that this is actually an internal clock divisor, which
affects the measurable speed range, not the read value. affects the measurable speed range, not the read value.
fan[1-*]_pulses Number of tachometer pulses per fan revolution.
Integer value, typically between 1 and 4.
RW
This value is a characteristic of the fan connected to the
device's input, so it has to be set in accordance with the fan
model.
Should only be created if the chip has a register to configure
the number of pulses. In the absence of such a register (and
thus attribute) the value assumed by all devices is 2 pulses
per fan revolution.
fan[1-*]_target fan[1-*]_target
Desired fan speed Desired fan speed
Unit: revolution/min (RPM) Unit: revolution/min (RPM)
......
...@@ -5,13 +5,11 @@ Supported chips: ...@@ -5,13 +5,11 @@ Supported chips:
* Winbond W83627EHF/EHG (ISA access ONLY) * Winbond W83627EHF/EHG (ISA access ONLY)
Prefix: 'w83627ehf' Prefix: 'w83627ehf'
Addresses scanned: ISA address retrieved from Super I/O registers Addresses scanned: ISA address retrieved from Super I/O registers
Datasheet: Datasheet: not available
http://www.nuvoton.com.tw/NR/rdonlyres/A6A258F0-F0C9-4F97-81C0-C4D29E7E943E/0/W83627EHF.pdf
* Winbond W83627DHG * Winbond W83627DHG
Prefix: 'w83627dhg' Prefix: 'w83627dhg'
Addresses scanned: ISA address retrieved from Super I/O registers Addresses scanned: ISA address retrieved from Super I/O registers
Datasheet: Datasheet: not available
http://www.nuvoton.com.tw/NR/rdonlyres/7885623D-A487-4CF9-A47F-30C5F73D6FE6/0/W83627DHG.pdf
* Winbond W83627DHG-P * Winbond W83627DHG-P
Prefix: 'w83627dhg' Prefix: 'w83627dhg'
Addresses scanned: ISA address retrieved from Super I/O registers Addresses scanned: ISA address retrieved from Super I/O registers
...@@ -24,6 +22,14 @@ Supported chips: ...@@ -24,6 +22,14 @@ Supported chips:
Prefix: 'w83667hg' Prefix: 'w83667hg'
Addresses scanned: ISA address retrieved from Super I/O registers Addresses scanned: ISA address retrieved from Super I/O registers
Datasheet: Available from Nuvoton upon request Datasheet: Available from Nuvoton upon request
* Nuvoton NCT6775F/W83667HG-I
Prefix: 'nct6775'
Addresses scanned: ISA address retrieved from Super I/O registers
Datasheet: Available from Nuvoton upon request
* Nuvoton NCT6776F
Prefix: 'nct6776'
Addresses scanned: ISA address retrieved from Super I/O registers
Datasheet: Available from Nuvoton upon request
Authors: Authors:
Jean Delvare <khali@linux-fr.org> Jean Delvare <khali@linux-fr.org>
...@@ -36,19 +42,28 @@ Description ...@@ -36,19 +42,28 @@ Description
----------- -----------
This driver implements support for the Winbond W83627EHF, W83627EHG, This driver implements support for the Winbond W83627EHF, W83627EHG,
W83627DHG, W83627DHG-P, W83667HG and W83667HG-B super I/O chips. W83627DHG, W83627DHG-P, W83667HG, W83667HG-B, W83667HG-I (NCT6775F),
We will refer to them collectively as Winbond chips. and NCT6776F super I/O chips. We will refer to them collectively as
Winbond chips.
The chips implement three temperature sensors, five fan rotation
speed sensors, ten analog voltage sensors (only nine for the 627DHG), one The chips implement three temperature sensors (up to four for 667HG-B, and nine
VID (6 pins for the 627EHF/EHG, 8 pins for the 627DHG and 667HG), alarms for NCT6775F and NCT6776F), five fan rotation speed sensors, ten analog voltage
with beep warnings (control unimplemented), and some automatic fan sensors (only nine for the 627DHG), one VID (6 pins for the 627EHF/EHG, 8 pins
regulation strategies (plus manual fan control mode). for the 627DHG and 667HG), alarms with beep warnings (control unimplemented),
and some automatic fan regulation strategies (plus manual fan control mode).
The temperature sensor sources on W82677HG-B, NCT6775F, and NCT6776F are
configurable. temp4 and higher attributes are only reported if its temperature
source differs from the temperature sources of the already reported temperature
sensors. The configured source for each of the temperature sensors is provided
in tempX_label.
Temperatures are measured in degrees Celsius and measurement resolution is 1 Temperatures are measured in degrees Celsius and measurement resolution is 1
degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when degC for temp1 and and 0.5 degC for temp2 and temp3. For temp4 and higher,
the temperature gets higher than high limit; it stays on until the temperature resolution is 1 degC for W83667HG-B and 0.0 degC for NCT6775F and NCT6776F.
falls below the hysteresis value. An alarm is triggered when the temperature gets higher than high limit;
it stays on until the temperature falls below the hysteresis value.
Alarms are only supported for temp1, temp2, and temp3.
Fan rotation speeds are reported in RPM (rotations per minute). An alarm is Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
triggered if the rotation speed has dropped below a programmable limit. Fan triggered if the rotation speed has dropped below a programmable limit. Fan
...@@ -80,7 +95,8 @@ prog -> pwm4 (not on 667HG and 667HG-B; the programmable setting is not ...@@ -80,7 +95,8 @@ prog -> pwm4 (not on 667HG and 667HG-B; the programmable setting is not
name - this is a standard hwmon device entry. For the W83627EHF and W83627EHG, name - this is a standard hwmon device entry. For the W83627EHF and W83627EHG,
it is set to "w83627ehf", for the W83627DHG it is set to "w83627dhg", it is set to "w83627ehf", for the W83627DHG it is set to "w83627dhg",
and for the W83667HG it is set to "w83667hg". for the W83667HG and W83667HG-B it is set to "w83667hg", for NCT6775F it
is set to "nct6775", and for NCT6776F it is set to "nct6776".
pwm[1-4] - this file stores PWM duty cycle or DC value (fan speed) in range: pwm[1-4] - this file stores PWM duty cycle or DC value (fan speed) in range:
0 (stop) to 255 (full) 0 (stop) to 255 (full)
...@@ -90,6 +106,18 @@ pwm[1-4]_enable - this file controls mode of fan/temperature control: ...@@ -90,6 +106,18 @@ pwm[1-4]_enable - this file controls mode of fan/temperature control:
* 2 "Thermal Cruise" mode * 2 "Thermal Cruise" mode
* 3 "Fan Speed Cruise" mode * 3 "Fan Speed Cruise" mode
* 4 "Smart Fan III" mode * 4 "Smart Fan III" mode
* 5 "Smart Fan IV" mode
SmartFan III mode is not supported on NCT6776F.
SmartFan IV mode is configurable only if it was configured at system
startup, and is only supported for W83677HG-B, NCT6775F, and NCT6776F.
SmartFan IV operational parameters can not be configured at this time,
and the various pwm attributes are not used in SmartFan IV mode.
The attributes can be written to, which is useful if you plan to
configure the system for a different pwm mode. However, the information
returned when reading pwm attributes is unrelated to SmartFan IV
operation.
pwm[1-4]_mode - controls if output is PWM or DC level pwm[1-4]_mode - controls if output is PWM or DC level
* 0 DC output (0 - 12v) * 0 DC output (0 - 12v)
......
...@@ -467,6 +467,17 @@ config SENSORS_JC42 ...@@ -467,6 +467,17 @@ config SENSORS_JC42
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 jc42. will be called jc42.
config SENSORS_LINEAGE
tristate "Lineage Compact Power Line Power Entry Module"
depends on I2C && EXPERIMENTAL
help
If you say yes here you get support for the Lineage Compact Power Line
series of DC/DC and AC/DC converters such as CP1800, CP2000AC,
CP2000DC, CP2725, and others.
This driver can also be built as a module. If so, the module
will be called lineage-pem.
config SENSORS_LM63 config SENSORS_LM63
tristate "National Semiconductor LM63 and LM64" tristate "National Semiconductor LM63 and LM64"
depends on I2C depends on I2C
...@@ -625,6 +636,17 @@ config SENSORS_LM93 ...@@ -625,6 +636,17 @@ config SENSORS_LM93
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 lm93. will be called lm93.
config SENSORS_LTC4151
tristate "Linear Technology LTC4151"
depends on I2C
default n
help
If you say yes here you get support for Linear Technology LTC4151
High Voltage I2C Current and Voltage Monitor interface.
This driver can also be built as a module. If so, the module will
be called ltc4151.
config SENSORS_LTC4215 config SENSORS_LTC4215
tristate "Linear Technology LTC4215" tristate "Linear Technology LTC4215"
depends on I2C && EXPERIMENTAL depends on I2C && EXPERIMENTAL
...@@ -685,6 +707,16 @@ config SENSORS_MAX1619 ...@@ -685,6 +707,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_MAX6639
tristate "Maxim MAX6639 sensor chip"
depends on I2C && EXPERIMENTAL
help
If you say yes here you get support for the MAX6639
sensor chips.
This driver can also be built as a module. If so, the module
will be called max6639.
config SENSORS_MAX6650 config SENSORS_MAX6650
tristate "Maxim MAX6650 sensor chip" tristate "Maxim MAX6650 sensor chip"
depends on I2C && EXPERIMENTAL depends on I2C && EXPERIMENTAL
...@@ -735,6 +767,61 @@ config SENSORS_PCF8591 ...@@ -735,6 +767,61 @@ 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
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_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.
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."
depends on GENERIC_GPIO depends on GENERIC_GPIO
...@@ -1083,7 +1170,7 @@ config SENSORS_W83627HF ...@@ -1083,7 +1170,7 @@ config SENSORS_W83627HF
will be called w83627hf. will be called w83627hf.
config SENSORS_W83627EHF config SENSORS_W83627EHF
tristate "Winbond W83627EHF/EHG/DHG, W83667HG" tristate "Winbond W83627EHF/EHG/DHG, W83667HG, NCT6775F, NCT6776F"
select HWMON_VID select HWMON_VID
help help
If you say yes here you get support for the hardware If you say yes here you get support for the hardware
...@@ -1094,7 +1181,8 @@ config SENSORS_W83627EHF ...@@ -1094,7 +1181,8 @@ config SENSORS_W83627EHF
chip suited for specific Intel processors that use PECI such as chip suited for specific Intel processors that use PECI such as
the Core 2 Duo. the Core 2 Duo.
This driver also supports the W83667HG chip. This driver also supports Nuvoton W83667HG, W83667HG-B, NCT6775F
(also known as W83667HG-I), and NCT6776F.
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 w83627ehf. will be called w83627ehf.
......
...@@ -62,6 +62,7 @@ obj-$(CONFIG_SENSORS_JC42) += jc42.o ...@@ -62,6 +62,7 @@ obj-$(CONFIG_SENSORS_JC42) += jc42.o
obj-$(CONFIG_SENSORS_JZ4740) += jz4740-hwmon.o obj-$(CONFIG_SENSORS_JZ4740) += jz4740-hwmon.o
obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o
obj-$(CONFIG_SENSORS_K10TEMP) += k10temp.o obj-$(CONFIG_SENSORS_K10TEMP) += k10temp.o
obj-$(CONFIG_SENSORS_LINEAGE) += lineage-pem.o
obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o
obj-$(CONFIG_SENSORS_LIS3_SPI) += lis3lv02d.o lis3lv02d_spi.o obj-$(CONFIG_SENSORS_LIS3_SPI) += lis3lv02d.o lis3lv02d_spi.o
obj-$(CONFIG_SENSORS_LIS3_I2C) += lis3lv02d.o lis3lv02d_i2c.o obj-$(CONFIG_SENSORS_LIS3_I2C) += lis3lv02d.o lis3lv02d_i2c.o
...@@ -79,11 +80,13 @@ obj-$(CONFIG_SENSORS_LM90) += lm90.o ...@@ -79,11 +80,13 @@ 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_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
obj-$(CONFIG_SENSORS_LTC4261) += ltc4261.o obj-$(CONFIG_SENSORS_LTC4261) += ltc4261.o
obj-$(CONFIG_SENSORS_MAX1111) += max1111.o obj-$(CONFIG_SENSORS_MAX1111) += max1111.o
obj-$(CONFIG_SENSORS_MAX1619) += max1619.o obj-$(CONFIG_SENSORS_MAX1619) += max1619.o
obj-$(CONFIG_SENSORS_MAX6639) += max6639.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_PC87360) += pc87360.o obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
...@@ -112,6 +115,13 @@ obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o ...@@ -112,6 +115,13 @@ 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_core.o
obj-$(CONFIG_SENSORS_PMBUS) += pmbus.o
obj-$(CONFIG_SENSORS_MAX16064) += max16064.o
obj-$(CONFIG_SENSORS_MAX34440) += max34440.o
obj-$(CONFIG_SENSORS_MAX8688) += max8688.o
ifeq ($(CONFIG_HWMON_DEBUG_CHIP),y) ifeq ($(CONFIG_HWMON_DEBUG_CHIP),y)
EXTRA_CFLAGS += -DDEBUG EXTRA_CFLAGS += -DDEBUG
endif endif
......
This diff is collapsed.
This diff is collapsed.
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/pm.h>
#include "lis3lv02d.h" #include "lis3lv02d.h"
...@@ -88,9 +89,10 @@ static int __devexit lis302dl_spi_remove(struct spi_device *spi) ...@@ -88,9 +89,10 @@ static int __devexit lis302dl_spi_remove(struct spi_device *spi)
return lis3lv02d_remove_fs(&lis3_dev); return lis3lv02d_remove_fs(&lis3_dev);
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM_SLEEP
static int lis3lv02d_spi_suspend(struct spi_device *spi, pm_message_t mesg) static int lis3lv02d_spi_suspend(struct device *dev)
{ {
struct spi_device *spi = to_spi_device(dev);
struct lis3lv02d *lis3 = spi_get_drvdata(spi); struct lis3lv02d *lis3 = spi_get_drvdata(spi);
if (!lis3->pdata || !lis3->pdata->wakeup_flags) if (!lis3->pdata || !lis3->pdata->wakeup_flags)
...@@ -99,8 +101,9 @@ static int lis3lv02d_spi_suspend(struct spi_device *spi, pm_message_t mesg) ...@@ -99,8 +101,9 @@ static int lis3lv02d_spi_suspend(struct spi_device *spi, pm_message_t mesg)
return 0; return 0;
} }
static int lis3lv02d_spi_resume(struct spi_device *spi) static int lis3lv02d_spi_resume(struct device *dev)
{ {
struct spi_device *spi = to_spi_device(dev);
struct lis3lv02d *lis3 = spi_get_drvdata(spi); struct lis3lv02d *lis3 = spi_get_drvdata(spi);
if (!lis3->pdata || !lis3->pdata->wakeup_flags) if (!lis3->pdata || !lis3->pdata->wakeup_flags)
...@@ -108,21 +111,19 @@ static int lis3lv02d_spi_resume(struct spi_device *spi) ...@@ -108,21 +111,19 @@ static int lis3lv02d_spi_resume(struct spi_device *spi)
return 0; return 0;
} }
#else
#define lis3lv02d_spi_suspend NULL
#define lis3lv02d_spi_resume NULL
#endif #endif
static SIMPLE_DEV_PM_OPS(lis3lv02d_spi_pm, lis3lv02d_spi_suspend,
lis3lv02d_spi_resume);
static struct spi_driver lis302dl_spi_driver = { static struct spi_driver lis302dl_spi_driver = {
.driver = { .driver = {
.name = DRV_NAME, .name = DRV_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = &lis3lv02d_spi_pm,
}, },
.probe = lis302dl_spi_probe, .probe = lis302dl_spi_probe,
.remove = __devexit_p(lis302dl_spi_remove), .remove = __devexit_p(lis302dl_spi_remove),
.suspend = lis3lv02d_spi_suspend,
.resume = lis3lv02d_spi_resume,
}; };
static int __init lis302dl_init(void) static int __init lis302dl_init(void)
......
...@@ -41,7 +41,7 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; ...@@ -41,7 +41,7 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
enum chips { enum chips {
any_chip, lm85b, lm85c, any_chip, lm85b, lm85c,
adm1027, adt7463, adt7468, adm1027, adt7463, adt7468,
emc6d100, emc6d102, emc6d103 emc6d100, emc6d102, emc6d103, emc6d103s
}; };
/* The LM85 registers */ /* The LM85 registers */
...@@ -283,10 +283,6 @@ struct lm85_zone { ...@@ -283,10 +283,6 @@ struct lm85_zone {
u8 hyst; /* Low limit hysteresis. (0-15) */ u8 hyst; /* Low limit hysteresis. (0-15) */
u8 range; /* Temp range, encoded */ u8 range; /* Temp range, encoded */
s8 critical; /* "All fans ON" temp limit */ s8 critical; /* "All fans ON" temp limit */
u8 off_desired; /* Actual "off" temperature specified. Preserved
* to prevent "drift" as other autofan control
* values change.
*/
u8 max_desired; /* Actual "max" temperature specified. Preserved u8 max_desired; /* Actual "max" temperature specified. Preserved
* to prevent "drift" as other autofan control * to prevent "drift" as other autofan control
* values change. * values change.
...@@ -306,6 +302,8 @@ struct lm85_data { ...@@ -306,6 +302,8 @@ struct lm85_data {
const int *freq_map; const int *freq_map;
enum chips type; enum chips type;
bool has_vid5; /* true if VID5 is configured for ADT7463 or ADT7468 */
struct mutex update_lock; struct mutex update_lock;
int valid; /* !=0 if following fields are valid */ int valid; /* !=0 if following fields are valid */
unsigned long last_reading; /* In jiffies */ unsigned long last_reading; /* In jiffies */
...@@ -352,6 +350,7 @@ static const struct i2c_device_id lm85_id[] = { ...@@ -352,6 +350,7 @@ static const struct i2c_device_id lm85_id[] = {
{ "emc6d101", emc6d100 }, { "emc6d101", emc6d100 },
{ "emc6d102", emc6d102 }, { "emc6d102", emc6d102 },
{ "emc6d103", emc6d103 }, { "emc6d103", emc6d103 },
{ "emc6d103s", emc6d103s },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, lm85_id); MODULE_DEVICE_TABLE(i2c, lm85_id);
...@@ -420,8 +419,7 @@ static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, ...@@ -420,8 +419,7 @@ static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr,
struct lm85_data *data = lm85_update_device(dev); struct lm85_data *data = lm85_update_device(dev);
int vid; int vid;
if ((data->type == adt7463 || data->type == adt7468) && if (data->has_vid5) {
(data->vid & 0x80)) {
/* 6-pin VID (VRM 10) */ /* 6-pin VID (VRM 10) */
vid = vid_from_reg(data->vid & 0x3f, data->vrm); vid = vid_from_reg(data->vid & 0x3f, data->vrm);
} else { } else {
...@@ -891,7 +889,6 @@ static ssize_t set_temp_auto_temp_off(struct device *dev, ...@@ -891,7 +889,6 @@ static ssize_t set_temp_auto_temp_off(struct device *dev,
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
min = TEMP_FROM_REG(data->zone[nr].limit); min = TEMP_FROM_REG(data->zone[nr].limit);
data->zone[nr].off_desired = TEMP_TO_REG(val);
data->zone[nr].hyst = HYST_TO_REG(min - val); data->zone[nr].hyst = HYST_TO_REG(min - val);
if (nr == 0 || nr == 1) { if (nr == 0 || nr == 1) {
lm85_write_value(client, LM85_REG_AFAN_HYST1, lm85_write_value(client, LM85_REG_AFAN_HYST1,
...@@ -934,18 +931,6 @@ static ssize_t set_temp_auto_temp_min(struct device *dev, ...@@ -934,18 +931,6 @@ static ssize_t set_temp_auto_temp_min(struct device *dev,
((data->zone[nr].range & 0x0f) << 4) ((data->zone[nr].range & 0x0f) << 4)
| (data->pwm_freq[nr] & 0x07)); | (data->pwm_freq[nr] & 0x07));
/* Update temp_auto_hyst and temp_auto_off */
data->zone[nr].hyst = HYST_TO_REG(TEMP_FROM_REG(
data->zone[nr].limit) - TEMP_FROM_REG(
data->zone[nr].off_desired));
if (nr == 0 || nr == 1) {
lm85_write_value(client, LM85_REG_AFAN_HYST1,
(data->zone[0].hyst << 4)
| data->zone[1].hyst);
} else {
lm85_write_value(client, LM85_REG_AFAN_HYST2,
(data->zone[2].hyst << 4));
}
mutex_unlock(&data->update_lock); mutex_unlock(&data->update_lock);
return count; return count;
} }
...@@ -1084,13 +1069,7 @@ static struct attribute *lm85_attributes[] = { ...@@ -1084,13 +1069,7 @@ static struct attribute *lm85_attributes[] = {
&sensor_dev_attr_pwm1_auto_pwm_min.dev_attr.attr, &sensor_dev_attr_pwm1_auto_pwm_min.dev_attr.attr,
&sensor_dev_attr_pwm2_auto_pwm_min.dev_attr.attr, &sensor_dev_attr_pwm2_auto_pwm_min.dev_attr.attr,
&sensor_dev_attr_pwm3_auto_pwm_min.dev_attr.attr, &sensor_dev_attr_pwm3_auto_pwm_min.dev_attr.attr,
&sensor_dev_attr_pwm1_auto_pwm_minctl.dev_attr.attr,
&sensor_dev_attr_pwm2_auto_pwm_minctl.dev_attr.attr,
&sensor_dev_attr_pwm3_auto_pwm_minctl.dev_attr.attr,
&sensor_dev_attr_temp1_auto_temp_off.dev_attr.attr,
&sensor_dev_attr_temp2_auto_temp_off.dev_attr.attr,
&sensor_dev_attr_temp3_auto_temp_off.dev_attr.attr,
&sensor_dev_attr_temp1_auto_temp_min.dev_attr.attr, &sensor_dev_attr_temp1_auto_temp_min.dev_attr.attr,
&sensor_dev_attr_temp2_auto_temp_min.dev_attr.attr, &sensor_dev_attr_temp2_auto_temp_min.dev_attr.attr,
&sensor_dev_attr_temp3_auto_temp_min.dev_attr.attr, &sensor_dev_attr_temp3_auto_temp_min.dev_attr.attr,
...@@ -1111,6 +1090,26 @@ static const struct attribute_group lm85_group = { ...@@ -1111,6 +1090,26 @@ static const struct attribute_group lm85_group = {
.attrs = lm85_attributes, .attrs = lm85_attributes,
}; };
static struct attribute *lm85_attributes_minctl[] = {
&sensor_dev_attr_pwm1_auto_pwm_minctl.dev_attr.attr,
&sensor_dev_attr_pwm2_auto_pwm_minctl.dev_attr.attr,
&sensor_dev_attr_pwm3_auto_pwm_minctl.dev_attr.attr,
};
static const struct attribute_group lm85_group_minctl = {
.attrs = lm85_attributes_minctl,
};
static struct attribute *lm85_attributes_temp_off[] = {
&sensor_dev_attr_temp1_auto_temp_off.dev_attr.attr,
&sensor_dev_attr_temp2_auto_temp_off.dev_attr.attr,
&sensor_dev_attr_temp3_auto_temp_off.dev_attr.attr,
};
static const struct attribute_group lm85_group_temp_off = {
.attrs = lm85_attributes_temp_off,
};
static struct attribute *lm85_attributes_in4[] = { static struct attribute *lm85_attributes_in4[] = {
&sensor_dev_attr_in4_input.dev_attr.attr, &sensor_dev_attr_in4_input.dev_attr.attr,
&sensor_dev_attr_in4_min.dev_attr.attr, &sensor_dev_attr_in4_min.dev_attr.attr,
...@@ -1258,16 +1257,9 @@ static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info) ...@@ -1258,16 +1257,9 @@ static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info)
case LM85_VERSTEP_EMC6D103_A1: case LM85_VERSTEP_EMC6D103_A1:
type_name = "emc6d103"; type_name = "emc6d103";
break; break;
/*
* Registers apparently missing in EMC6D103S/EMC6D103:A2
* compared to EMC6D103:A0, EMC6D103:A1, and EMC6D102
* (according to the data sheets), but used unconditionally
* in the driver: 62[5:7], 6D[0:7], and 6E[0:7].
* So skip EMC6D103S for now.
case LM85_VERSTEP_EMC6D103S: case LM85_VERSTEP_EMC6D103S:
type_name = "emc6d103s"; type_name = "emc6d103s";
break; break;
*/
} }
} else { } else {
dev_dbg(&adapter->dev, dev_dbg(&adapter->dev,
...@@ -1280,6 +1272,19 @@ static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info) ...@@ -1280,6 +1272,19 @@ static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info)
return 0; return 0;
} }
static void lm85_remove_files(struct i2c_client *client, struct lm85_data *data)
{
sysfs_remove_group(&client->dev.kobj, &lm85_group);
if (data->type != emc6d103s) {
sysfs_remove_group(&client->dev.kobj, &lm85_group_minctl);
sysfs_remove_group(&client->dev.kobj, &lm85_group_temp_off);
}
if (!data->has_vid5)
sysfs_remove_group(&client->dev.kobj, &lm85_group_in4);
if (data->type == emc6d100)
sysfs_remove_group(&client->dev.kobj, &lm85_group_in567);
}
static int lm85_probe(struct i2c_client *client, static int lm85_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
...@@ -1302,6 +1307,7 @@ static int lm85_probe(struct i2c_client *client, ...@@ -1302,6 +1307,7 @@ static int lm85_probe(struct i2c_client *client,
case emc6d100: case emc6d100:
case emc6d102: case emc6d102:
case emc6d103: case emc6d103:
case emc6d103s:
data->freq_map = adm1027_freq_map; data->freq_map = adm1027_freq_map;
break; break;
default: default:
...@@ -1319,11 +1325,26 @@ static int lm85_probe(struct i2c_client *client, ...@@ -1319,11 +1325,26 @@ static int lm85_probe(struct i2c_client *client,
if (err) if (err)
goto err_kfree; goto err_kfree;
/* minctl and temp_off exist on all chips except emc6d103s */
if (data->type != emc6d103s) {
err = sysfs_create_group(&client->dev.kobj, &lm85_group_minctl);
if (err)
goto err_kfree;
err = sysfs_create_group(&client->dev.kobj,
&lm85_group_temp_off);
if (err)
goto err_kfree;
}
/* The ADT7463/68 have an optional VRM 10 mode where pin 21 is used /* The ADT7463/68 have an optional VRM 10 mode where pin 21 is used
as a sixth digital VID input rather than an analog input. */ as a sixth digital VID input rather than an analog input. */
data->vid = lm85_read_value(client, LM85_REG_VID); if (data->type == adt7463 || data->type == adt7468) {
if (!((data->type == adt7463 || data->type == adt7468) && u8 vid = lm85_read_value(client, LM85_REG_VID);
(data->vid & 0x80))) if (vid & 0x80)
data->has_vid5 = true;
}
if (!data->has_vid5)
if ((err = sysfs_create_group(&client->dev.kobj, if ((err = sysfs_create_group(&client->dev.kobj,
&lm85_group_in4))) &lm85_group_in4)))
goto err_remove_files; goto err_remove_files;
...@@ -1344,10 +1365,7 @@ static int lm85_probe(struct i2c_client *client, ...@@ -1344,10 +1365,7 @@ static int lm85_probe(struct i2c_client *client,
/* Error out and cleanup code */ /* Error out and cleanup code */
err_remove_files: err_remove_files:
sysfs_remove_group(&client->dev.kobj, &lm85_group); lm85_remove_files(client, data);
sysfs_remove_group(&client->dev.kobj, &lm85_group_in4);
if (data->type == emc6d100)
sysfs_remove_group(&client->dev.kobj, &lm85_group_in567);
err_kfree: err_kfree:
kfree(data); kfree(data);
return err; return err;
...@@ -1357,10 +1375,7 @@ static int lm85_remove(struct i2c_client *client) ...@@ -1357,10 +1375,7 @@ static int lm85_remove(struct i2c_client *client)
{ {
struct lm85_data *data = i2c_get_clientdata(client); struct lm85_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm85_group); lm85_remove_files(client, data);
sysfs_remove_group(&client->dev.kobj, &lm85_group_in4);
if (data->type == emc6d100)
sysfs_remove_group(&client->dev.kobj, &lm85_group_in567);
kfree(data); kfree(data);
return 0; return 0;
} }
...@@ -1457,11 +1472,8 @@ static struct lm85_data *lm85_update_device(struct device *dev) ...@@ -1457,11 +1472,8 @@ static struct lm85_data *lm85_update_device(struct device *dev)
lm85_read_value(client, LM85_REG_FAN(i)); lm85_read_value(client, LM85_REG_FAN(i));
} }
if (!((data->type == adt7463 || data->type == adt7468) && if (!data->has_vid5)
(data->vid & 0x80))) { data->in[4] = lm85_read_value(client, LM85_REG_IN(4));
data->in[4] = lm85_read_value(client,
LM85_REG_IN(4));
}
if (data->type == adt7468) if (data->type == adt7468)
data->cfg5 = lm85_read_value(client, ADT7468_REG_CFG5); data->cfg5 = lm85_read_value(client, ADT7468_REG_CFG5);
...@@ -1487,7 +1499,8 @@ static struct lm85_data *lm85_update_device(struct device *dev) ...@@ -1487,7 +1499,8 @@ static struct lm85_data *lm85_update_device(struct device *dev)
/* More alarm bits */ /* More alarm bits */
data->alarms |= lm85_read_value(client, data->alarms |= lm85_read_value(client,
EMC6D100_REG_ALARM3) << 16; EMC6D100_REG_ALARM3) << 16;
} else if (data->type == emc6d102 || data->type == emc6d103) { } else if (data->type == emc6d102 || data->type == emc6d103 ||
data->type == emc6d103s) {
/* Have to read LSB bits after the MSB ones because /* Have to read LSB bits after the MSB ones because
the reading of the MSB bits has frozen the the reading of the MSB bits has frozen the
LSBs (backward from the ADM1027). LSBs (backward from the ADM1027).
...@@ -1528,8 +1541,7 @@ static struct lm85_data *lm85_update_device(struct device *dev) ...@@ -1528,8 +1541,7 @@ static struct lm85_data *lm85_update_device(struct device *dev)
lm85_read_value(client, LM85_REG_FAN_MIN(i)); lm85_read_value(client, LM85_REG_FAN_MIN(i));
} }
if (!((data->type == adt7463 || data->type == adt7468) && if (!data->has_vid5) {
(data->vid & 0x80))) {
data->in_min[4] = lm85_read_value(client, data->in_min[4] = lm85_read_value(client,
LM85_REG_IN_MIN(4)); LM85_REG_IN_MIN(4));
data->in_max[4] = lm85_read_value(client, data->in_max[4] = lm85_read_value(client,
...@@ -1573,17 +1585,19 @@ static struct lm85_data *lm85_update_device(struct device *dev) ...@@ -1573,17 +1585,19 @@ static struct lm85_data *lm85_update_device(struct device *dev)
} }
} }
i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1); if (data->type != emc6d103s) {
data->autofan[0].min_off = (i & 0x20) != 0; i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1);
data->autofan[1].min_off = (i & 0x40) != 0; data->autofan[0].min_off = (i & 0x20) != 0;
data->autofan[2].min_off = (i & 0x80) != 0; data->autofan[1].min_off = (i & 0x40) != 0;
data->autofan[2].min_off = (i & 0x80) != 0;
i = lm85_read_value(client, LM85_REG_AFAN_HYST1); i = lm85_read_value(client, LM85_REG_AFAN_HYST1);
data->zone[0].hyst = i >> 4; data->zone[0].hyst = i >> 4;
data->zone[1].hyst = i & 0x0f; data->zone[1].hyst = i & 0x0f;
i = lm85_read_value(client, LM85_REG_AFAN_HYST2); i = lm85_read_value(client, LM85_REG_AFAN_HYST2);
data->zone[2].hyst = i >> 4; data->zone[2].hyst = i >> 4;
}
data->last_config = jiffies; data->last_config = jiffies;
} /* last_config */ } /* last_config */
......
/*
* Driver for Linear Technology LTC4151 High Voltage I2C Current
* and Voltage Monitor
*
* Copyright (C) 2011 AppearTV AS
*
* Derived from:
*
* Driver for Linear Technology LTC4261 I2C Negative Voltage Hot
* Swap Controller
* Copyright (C) 2010 Ericsson AB.
*
* Datasheet: http://www.linear.com/docs/Datasheet/4151fc.pdf
*
* 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 <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
/* chip registers */
#define LTC4151_SENSE_H 0x00
#define LTC4151_SENSE_L 0x01
#define LTC4151_VIN_H 0x02
#define LTC4151_VIN_L 0x03
#define LTC4151_ADIN_H 0x04
#define LTC4151_ADIN_L 0x05
struct ltc4151_data {
struct device *hwmon_dev;
struct mutex update_lock;
bool valid;
unsigned long last_updated; /* in jiffies */
/* Registers */
u8 regs[6];
};
static struct ltc4151_data *ltc4151_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct ltc4151_data *data = i2c_get_clientdata(client);
struct ltc4151_data *ret = data;
mutex_lock(&data->update_lock);
/*
* The chip's A/D updates 6 times per second
* (Conversion Rate 6 - 9 Hz)
*/
if (time_after(jiffies, data->last_updated + HZ / 6) || !data->valid) {
int i;
dev_dbg(&client->dev, "Starting ltc4151 update\n");
/* Read all registers */
for (i = 0; i < ARRAY_SIZE(data->regs); i++) {
int val;
val = i2c_smbus_read_byte_data(client, i);
if (unlikely(val < 0)) {
dev_dbg(dev,
"Failed to read ADC value: error %d\n",
val);
ret = ERR_PTR(val);
goto abort;
}
data->regs[i] = val;
}
data->last_updated = jiffies;
data->valid = 1;
}
abort:
mutex_unlock(&data->update_lock);
return ret;
}
/* Return the voltage from the given register in mV */
static int ltc4151_get_value(struct ltc4151_data *data, u8 reg)
{
u32 val;
val = (data->regs[reg] << 4) + (data->regs[reg + 1] >> 4);
switch (reg) {
case LTC4151_ADIN_H:
/* 500uV resolution. Convert to mV. */
val = val * 500 / 1000;
break;
case LTC4151_SENSE_H:
/*
* 20uV resolution. Convert to current as measured with
* an 1 mOhm sense resistor, in mA.
*/
val = val * 20;
break;
case LTC4151_VIN_H:
/* 25 mV per increment */
val = val * 25;
break;
default:
/* If we get here, the developer messed up */
WARN_ON_ONCE(1);
val = 0;
break;
}
return val;
}
static ssize_t ltc4151_show_value(struct device *dev,
struct device_attribute *da, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct ltc4151_data *data = ltc4151_update_device(dev);
int value;
if (IS_ERR(data))
return PTR_ERR(data);
value = ltc4151_get_value(data, attr->index);
return snprintf(buf, PAGE_SIZE, "%d\n", value);
}
/*
* Input voltages.
*/
static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, \
ltc4151_show_value, NULL, LTC4151_VIN_H);
static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, \
ltc4151_show_value, NULL, LTC4151_ADIN_H);
/* Currents (via sense resistor) */
static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, \
ltc4151_show_value, NULL, LTC4151_SENSE_H);
/* Finally, construct an array of pointers to members of the above objects,
* as required for sysfs_create_group()
*/
static struct attribute *ltc4151_attributes[] = {
&sensor_dev_attr_in1_input.dev_attr.attr,
&sensor_dev_attr_in2_input.dev_attr.attr,
&sensor_dev_attr_curr1_input.dev_attr.attr,
NULL,
};
static const struct attribute_group ltc4151_group = {
.attrs = ltc4151_attributes,
};
static int ltc4151_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct i2c_adapter *adapter = client->adapter;
struct ltc4151_data *data;
int ret;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV;
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data) {
ret = -ENOMEM;
goto out_kzalloc;
}
i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
/* Register sysfs hooks */
ret = sysfs_create_group(&client->dev.kobj, &ltc4151_group);
if (ret)
goto out_sysfs_create_group;
data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) {
ret = PTR_ERR(data->hwmon_dev);
goto out_hwmon_device_register;
}
return 0;
out_hwmon_device_register:
sysfs_remove_group(&client->dev.kobj, &ltc4151_group);
out_sysfs_create_group:
kfree(data);
out_kzalloc:
return ret;
}
static int ltc4151_remove(struct i2c_client *client)
{
struct ltc4151_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &ltc4151_group);
kfree(data);
return 0;
}
static const struct i2c_device_id ltc4151_id[] = {
{ "ltc4151", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ltc4151_id);
/* This is the driver that will be inserted */
static struct i2c_driver ltc4151_driver = {
.driver = {
.name = "ltc4151",
},
.probe = ltc4151_probe,
.remove = ltc4151_remove,
.id_table = ltc4151_id,
};
static int __init ltc4151_init(void)
{
return i2c_add_driver(&ltc4151_driver);
}
static void __exit ltc4151_exit(void)
{
i2c_del_driver(&ltc4151_driver);
}
MODULE_AUTHOR("Per Dalen <per.dalen@appeartv.com>");
MODULE_DESCRIPTION("LTC4151 driver");
MODULE_LICENSE("GPL");
module_init(ltc4151_init);
module_exit(ltc4151_exit);
/*
* Hardware monitoring driver for Maxim MAX16064
*
* 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/i2c.h>
#include "pmbus.h"
static struct pmbus_driver_info max16064_info = {
.pages = 4,
.direct[PSC_VOLTAGE_IN] = true,
.direct[PSC_VOLTAGE_OUT] = true,
.direct[PSC_TEMPERATURE] = true,
.m[PSC_VOLTAGE_IN] = 19995,
.b[PSC_VOLTAGE_IN] = 0,
.R[PSC_VOLTAGE_IN] = -1,
.m[PSC_VOLTAGE_OUT] = 19995,
.b[PSC_VOLTAGE_OUT] = 0,
.R[PSC_VOLTAGE_OUT] = -1,
.m[PSC_TEMPERATURE] = -7612,
.b[PSC_TEMPERATURE] = 335,
.R[PSC_TEMPERATURE] = -3,
.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_TEMP
| PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_TEMP,
.func[1] = 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,
};
static int max16064_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
return pmbus_do_probe(client, id, &max16064_info);
}
static int max16064_remove(struct i2c_client *client)
{
return pmbus_do_remove(client);
}
static const struct i2c_device_id max16064_id[] = {
{"max16064", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, max16064_id);
/* This is the driver that will be inserted */
static struct i2c_driver max16064_driver = {
.driver = {
.name = "max16064",
},
.probe = max16064_probe,
.remove = max16064_remove,
.id_table = max16064_id,
};
static int __init max16064_init(void)
{
return i2c_add_driver(&max16064_driver);
}
static void __exit max16064_exit(void)
{
i2c_del_driver(&max16064_driver);
}
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for Maxim MAX16064");
MODULE_LICENSE("GPL");
module_init(max16064_init);
module_exit(max16064_exit);
/*
* Hardware monitoring driver for Maxim MAX34440/MAX34441
*
* 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/i2c.h>
#include "pmbus.h"
enum chips { max34440, max34441 };
#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)
static int max34440_get_status(struct i2c_client *client, int page, int reg)
{
int ret;
int mfg_status;
ret = pmbus_set_page(client, page);
if (ret < 0)
return ret;
switch (reg) {
case PMBUS_STATUS_IOUT:
mfg_status = pmbus_read_word_data(client, 0,
PMBUS_STATUS_MFR_SPECIFIC);
if (mfg_status < 0)
return mfg_status;
if (mfg_status & MAX34440_STATUS_OC_WARN)
ret |= PB_IOUT_OC_WARNING;
if (mfg_status & MAX34440_STATUS_OC_FAULT)
ret |= PB_IOUT_OC_FAULT;
break;
case PMBUS_STATUS_TEMPERATURE:
mfg_status = pmbus_read_word_data(client, 0,
PMBUS_STATUS_MFR_SPECIFIC);
if (mfg_status < 0)
return mfg_status;
if (mfg_status & MAX34440_STATUS_OT_WARN)
ret |= PB_TEMP_OT_WARNING;
if (mfg_status & MAX34440_STATUS_OT_FAULT)
ret |= PB_TEMP_OT_FAULT;
break;
default:
ret = -ENODATA;
break;
}
return ret;
}
static struct pmbus_driver_info max34440_info[] = {
[max34440] = {
.pages = 14,
.direct[PSC_VOLTAGE_IN] = true,
.direct[PSC_VOLTAGE_OUT] = true,
.direct[PSC_TEMPERATURE] = true,
.direct[PSC_CURRENT_OUT] = true,
.m[PSC_VOLTAGE_IN] = 1,
.b[PSC_VOLTAGE_IN] = 0,
.R[PSC_VOLTAGE_IN] = 3, /* R = 0 in datasheet reflects mV */
.m[PSC_VOLTAGE_OUT] = 1,
.b[PSC_VOLTAGE_OUT] = 0,
.R[PSC_VOLTAGE_OUT] = 3, /* R = 0 in datasheet reflects mV */
.m[PSC_CURRENT_OUT] = 1,
.b[PSC_CURRENT_OUT] = 0,
.R[PSC_CURRENT_OUT] = 3, /* R = 0 in datasheet reflects mA */
.m[PSC_TEMPERATURE] = 1,
.b[PSC_TEMPERATURE] = 0,
.R[PSC_TEMPERATURE] = 2,
.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
.func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
.func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
.func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
.func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
.func[5] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
.func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
.func[7] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
.func[8] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
.func[9] = 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[12] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
.func[13] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
.get_status = max34440_get_status,
},
[max34441] = {
.pages = 12,
.direct[PSC_VOLTAGE_IN] = true,
.direct[PSC_VOLTAGE_OUT] = true,
.direct[PSC_TEMPERATURE] = true,
.direct[PSC_CURRENT_OUT] = true,
.direct[PSC_FAN] = true,
.m[PSC_VOLTAGE_IN] = 1,
.b[PSC_VOLTAGE_IN] = 0,
.R[PSC_VOLTAGE_IN] = 3,
.m[PSC_VOLTAGE_OUT] = 1,
.b[PSC_VOLTAGE_OUT] = 0,
.R[PSC_VOLTAGE_OUT] = 3,
.m[PSC_CURRENT_OUT] = 1,
.b[PSC_CURRENT_OUT] = 0,
.R[PSC_CURRENT_OUT] = 3,
.m[PSC_TEMPERATURE] = 1,
.b[PSC_TEMPERATURE] = 0,
.R[PSC_TEMPERATURE] = 2,
.m[PSC_FAN] = 1,
.b[PSC_FAN] = 0,
.R[PSC_FAN] = 0,
.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
.func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
.func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
.func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
.func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
.func[5] = PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12,
.func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
.func[7] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
.func[8] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
.func[9] = 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,
.get_status = max34440_get_status,
},
};
static int max34440_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
return pmbus_do_probe(client, id, &max34440_info[id->driver_data]);
}
static int max34440_remove(struct i2c_client *client)
{
return pmbus_do_remove(client);
}
static const struct i2c_device_id max34440_id[] = {
{"max34440", max34440},
{"max34441", max34441},
{}
};
MODULE_DEVICE_TABLE(i2c, max34440_id);
/* This is the driver that will be inserted */
static struct i2c_driver max34440_driver = {
.driver = {
.name = "max34440",
},
.probe = max34440_probe,
.remove = max34440_remove,
.id_table = max34440_id,
};
static int __init max34440_init(void)
{
return i2c_add_driver(&max34440_driver);
}
static void __exit max34440_exit(void)
{
i2c_del_driver(&max34440_driver);
}
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for Maxim MAX34440/MAX34441");
MODULE_LICENSE("GPL");
module_init(max34440_init);
module_exit(max34440_exit);
This diff is collapsed.
/*
* Hardware monitoring driver for Maxim MAX8688
*
* 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/i2c.h>
#include "pmbus.h"
#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)
static int max8688_get_status(struct i2c_client *client, int page, int reg)
{
int ret = 0;
int mfg_status;
if (page)
return -EINVAL;
switch (reg) {
case PMBUS_STATUS_VOUT:
mfg_status = pmbus_read_word_data(client, 0,
MAX8688_MFG_STATUS);
if (mfg_status < 0)
return mfg_status;
if (mfg_status & MAX8688_STATUS_UV_WARNING)
ret |= PB_VOLTAGE_UV_WARNING;
if (mfg_status & MAX8688_STATUS_UV_FAULT)
ret |= PB_VOLTAGE_UV_FAULT;
if (mfg_status & MAX8688_STATUS_OV_WARNING)
ret |= PB_VOLTAGE_OV_WARNING;
if (mfg_status & MAX8688_STATUS_OV_FAULT)
ret |= PB_VOLTAGE_OV_FAULT;
break;
case PMBUS_STATUS_IOUT:
mfg_status = pmbus_read_word_data(client, 0,
MAX8688_MFG_STATUS);
if (mfg_status < 0)
return mfg_status;
if (mfg_status & MAX8688_STATUS_UC_FAULT)
ret |= PB_IOUT_UC_FAULT;
if (mfg_status & MAX8688_STATUS_OC_WARNING)
ret |= PB_IOUT_OC_WARNING;
if (mfg_status & MAX8688_STATUS_OC_FAULT)
ret |= PB_IOUT_OC_FAULT;
break;
case PMBUS_STATUS_TEMPERATURE:
mfg_status = pmbus_read_word_data(client, 0,
MAX8688_MFG_STATUS);
if (mfg_status < 0)
return mfg_status;
if (mfg_status & MAX8688_STATUS_OT_WARNING)
ret |= PB_TEMP_OT_WARNING;
if (mfg_status & MAX8688_STATUS_OT_FAULT)
ret |= PB_TEMP_OT_FAULT;
break;
default:
ret = -ENODATA;
break;
}
return ret;
}
static struct pmbus_driver_info max8688_info = {
.pages = 1,
.direct[PSC_VOLTAGE_IN] = true,
.direct[PSC_VOLTAGE_OUT] = true,
.direct[PSC_TEMPERATURE] = true,
.direct[PSC_CURRENT_OUT] = true,
.m[PSC_VOLTAGE_IN] = 19995,
.b[PSC_VOLTAGE_IN] = 0,
.R[PSC_VOLTAGE_IN] = -1,
.m[PSC_VOLTAGE_OUT] = 19995,
.b[PSC_VOLTAGE_OUT] = 0,
.R[PSC_VOLTAGE_OUT] = -1,
.m[PSC_CURRENT_OUT] = 23109,
.b[PSC_CURRENT_OUT] = 0,
.R[PSC_CURRENT_OUT] = -2,
.m[PSC_TEMPERATURE] = -7612,
.b[PSC_TEMPERATURE] = 335,
.R[PSC_TEMPERATURE] = -3,
.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT | PMBUS_HAVE_TEMP
| PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT
| PMBUS_HAVE_STATUS_TEMP,
.get_status = max8688_get_status,
};
static int max8688_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
return pmbus_do_probe(client, id, &max8688_info);
}
static int max8688_remove(struct i2c_client *client)
{
return pmbus_do_remove(client);
}
static const struct i2c_device_id max8688_id[] = {
{"max8688", 0},
{ }
};
MODULE_DEVICE_TABLE(i2c, max8688_id);
/* This is the driver that will be inserted */
static struct i2c_driver max8688_driver = {
.driver = {
.name = "max8688",
},
.probe = max8688_probe,
.remove = max8688_remove,
.id_table = max8688_id,
};
static int __init max8688_init(void)
{
return i2c_add_driver(&max8688_driver);
}
static void __exit max8688_exit(void)
{
i2c_del_driver(&max8688_driver);
}
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for Maxim MAX8688");
MODULE_LICENSE("GPL");
module_init(max8688_init);
module_exit(max8688_exit);
/*
* Hardware monitoring driver for PMBus devices
*
* Copyright (c) 2010, 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/mutex.h>
#include <linux/i2c.h>
#include "pmbus.h"
/*
* Find sensor groups and status registers on each page.
*/
static void pmbus_find_sensor_groups(struct i2c_client *client,
struct pmbus_driver_info *info)
{
int page;
/* Sensors detected on page 0 only */
if (pmbus_check_word_register(client, 0, PMBUS_READ_VIN))
info->func[0] |= PMBUS_HAVE_VIN;
if (pmbus_check_word_register(client, 0, PMBUS_READ_VCAP))
info->func[0] |= PMBUS_HAVE_VCAP;
if (pmbus_check_word_register(client, 0, PMBUS_READ_IIN))
info->func[0] |= PMBUS_HAVE_IIN;
if (pmbus_check_word_register(client, 0, PMBUS_READ_PIN))
info->func[0] |= PMBUS_HAVE_PIN;
if (info->func[0]
&& pmbus_check_byte_register(client, 0, PMBUS_STATUS_INPUT))
info->func[0] |= PMBUS_HAVE_STATUS_INPUT;
if (pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_1)) {
info->func[0] |= PMBUS_HAVE_FAN12;
if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_12))
info->func[0] |= PMBUS_HAVE_STATUS_FAN12;
}
if (pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_3)) {
info->func[0] |= PMBUS_HAVE_FAN34;
if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_34))
info->func[0] |= PMBUS_HAVE_STATUS_FAN34;
}
if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_1)) {
info->func[0] |= PMBUS_HAVE_TEMP;
if (pmbus_check_byte_register(client, 0,
PMBUS_STATUS_TEMPERATURE))
info->func[0] |= PMBUS_HAVE_STATUS_TEMP;
}
/* Sensors detected on all pages */
for (page = 0; page < info->pages; page++) {
if (pmbus_check_word_register(client, page, PMBUS_READ_VOUT)) {
info->func[page] |= PMBUS_HAVE_VOUT;
if (pmbus_check_byte_register(client, page,
PMBUS_STATUS_VOUT))
info->func[page] |= PMBUS_HAVE_STATUS_VOUT;
}
if (pmbus_check_word_register(client, page, PMBUS_READ_IOUT)) {
info->func[page] |= PMBUS_HAVE_IOUT;
if (pmbus_check_byte_register(client, 0,
PMBUS_STATUS_IOUT))
info->func[page] |= PMBUS_HAVE_STATUS_IOUT;
}
if (pmbus_check_word_register(client, page, PMBUS_READ_POUT))
info->func[page] |= PMBUS_HAVE_POUT;
}
}
/*
* Identify chip parameters.
*/
static int pmbus_identify(struct i2c_client *client,
struct pmbus_driver_info *info)
{
if (!info->pages) {
/*
* Check if the PAGE command is supported. If it is,
* keep setting the page number until it fails or until the
* maximum number of pages has been reached. Assume that
* this is the number of pages supported by the chip.
*/
if (pmbus_check_byte_register(client, 0, PMBUS_PAGE)) {
int page;
for (page = 1; page < PMBUS_PAGES; page++) {
if (pmbus_set_page(client, page) < 0)
break;
}
pmbus_set_page(client, 0);
info->pages = page;
} else {
info->pages = 1;
}
}
/*
* We should check if the COEFFICIENTS register is supported.
* If it is, and the chip is configured for direct mode, we can read
* the coefficients from the chip, one set per group of sensor
* registers.
*
* To do this, we will need access to a chip which actually supports the
* COEFFICIENTS command, since the command is too complex to implement
* without testing it.
*/
/* Try to find sensor groups */
pmbus_find_sensor_groups(client, info);
return 0;
}
static int pmbus_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct pmbus_driver_info *info;
int ret;
info = kzalloc(sizeof(struct pmbus_driver_info), GFP_KERNEL);
if (!info)
return -ENOMEM;
info->pages = id->driver_data;
info->identify = pmbus_identify;
ret = pmbus_do_probe(client, id, info);
if (ret < 0)
goto out;
return 0;
out:
kfree(info);
return ret;
}
static int pmbus_remove(struct i2c_client *client)
{
int ret;
const struct pmbus_driver_info *info;
info = pmbus_get_driver_info(client);
ret = pmbus_do_remove(client);
kfree(info);
return ret;
}
/*
* Use driver_data to set the number of pages supported by the chip.
*/
static const struct i2c_device_id pmbus_id[] = {
{"bmr450", 1},
{"bmr451", 1},
{"bmr453", 1},
{"bmr454", 1},
{"ltc2978", 8},
{"pmbus", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, pmbus_id);
/* This is the driver that will be inserted */
static struct i2c_driver pmbus_driver = {
.driver = {
.name = "pmbus",
},
.probe = pmbus_probe,
.remove = pmbus_remove,
.id_table = pmbus_id,
};
static int __init pmbus_init(void)
{
return i2c_add_driver(&pmbus_driver);
}
static void __exit pmbus_exit(void)
{
i2c_del_driver(&pmbus_driver);
}
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("Generic PMBus driver");
MODULE_LICENSE("GPL");
module_init(pmbus_init);
module_exit(pmbus_exit);
/*
* pmbus.h - Common defines and structures for PMBus devices
*
* Copyright (c) 2010, 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.
*/
#ifndef PMBUS_H
#define PMBUS_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
/*
* CAPABILITY
*/
#define PB_CAPABILITY_SMBALERT (1<<4)
#define PB_CAPABILITY_ERROR_CHECK (1<<7)
/*
* VOUT_MODE
*/
#define PB_VOUT_MODE_MODE_MASK 0xe0
#define PB_VOUT_MODE_PARAM_MASK 0x1f
#define PB_VOUT_MODE_LINEAR 0x00
#define PB_VOUT_MODE_VID 0x20
#define PB_VOUT_MODE_DIRECT 0x40
/*
* 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)
/*
* 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)
/*
* 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)
/*
* 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)
/*
* 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)
/*
* STATUS_INPUT
*/
#define PB_PIN_OP_WARNING (1<<0)
#define PB_IIN_OC_WARNING (1<<1)
#define PB_IIN_OC_FAULT (1<<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)
/*
* 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)
/*
* 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)
enum pmbus_sensor_classes {
PSC_VOLTAGE_IN = 0,
PSC_VOLTAGE_OUT,
PSC_CURRENT_IN,
PSC_CURRENT_OUT,
PSC_POWER,
PSC_TEMPERATURE,
PSC_FAN,
PSC_NUM_CLASSES /* Number of power 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)
struct pmbus_driver_info {
int pages; /* Total number of pages */
bool direct[PSC_NUM_CLASSES];
/* true if device uses direct data format
for the given sensor class */
/*
* Support one set of coefficients for each sensor type
* Used for chips providing data in direct mode.
*/
int m[PSC_NUM_CLASSES]; /* mantissa for direct data format */
int b[PSC_NUM_CLASSES]; /* offset */
int R[PSC_NUM_CLASSES]; /* exponent */
u32 func[PMBUS_PAGES]; /* Functionality, per page */
/*
* The get_status function maps manufacturing specific status values
* into PMBus standard status values.
* This function is optional and only necessary if chip specific status
* register values have to be mapped into standard PMBus status register
* values.
*/
int (*get_status)(struct i2c_client *client, int page, int reg);
/*
* The identify function determines supported PMBus functionality.
* This function is only necessary if a chip driver supports multiple
* chips, and the chip functionality is not pre-determined.
*/
int (*identify)(struct i2c_client *client,
struct pmbus_driver_info *info);
};
/* Function declarations */
int pmbus_set_page(struct i2c_client *client, u8 page);
int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg);
void pmbus_clear_faults(struct i2c_client *client);
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);
int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
struct pmbus_driver_info *info);
int pmbus_do_remove(struct i2c_client *client);
const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client
*client);
#endif /* PMBUS_H */
This diff is collapsed.
This diff is collapsed.
#ifndef _LINUX_MAX6639_H
#define _LINUX_MAX6639_H
#include <linux/types.h>
/* platform data for the MAX6639 temperature sensor and fan control */
struct max6639_platform_data {
bool pwm_polarity; /* Polarity low (0) or high (1, default) */
int ppr; /* Pulses per rotation 1..4 (default == 2) */
int rpm_range; /* 2000, 4000 (default), 8000 or 16000 */
};
#endif /* _LINUX_MAX6639_H */
/*
* Hardware monitoring driver for PMBus devices
*
* Copyright (c) 2010, 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.
*/
#ifndef _PMBUS_H_
#define _PMBUS_H_
/* flags */
/*
* PMBUS_SKIP_STATUS_CHECK
*
* During register detection, skip checking the status register for
* communication or command errors.
*
* Some PMBus chips respond with valid data when trying to read an unsupported
* register. For such chips, checking the status register is mandatory when
* trying to determine if a chip register exists or not.
* Other PMBus chips don't support the STATUS_CML register, or report
* communication errors for no explicable reason. For such chips, checking
* the status register must be disabled.
*/
#define PMBUS_SKIP_STATUS_CHECK (1 << 0)
struct pmbus_platform_data {
u32 flags; /* Device specific flags */
};
#endif /* _PMBUS_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