提交 6fad2b5b 编写于 作者: L 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:
  hwmon: (coretemp) Fix checkpatch errors
  hwmon: Remove pkgtemp driver
  hwmon: (coretemp) Merge pkgtemp with coretemp
  hwmon: (pmbus) Add support for Analog Devices ADM1275
  hwmon: (pmbus) Support for TI UCD90xxx series Sequencer and System Health Controllers
  hwmon: (pmbus) Add support for TI UCD9200 series of PWM System Controllers
  hwmon: (pmbus) Use device specific function to read fan configuration
  hwmon: (pmbus) Expand scope of device specific get_status function
  hwmon: (pmbus) Introduce infrastructure to detect sensors and limit registers
  hwmon: Driver for MAX16065 System Manager and compatibles
  hwmon: (sht15) add support for CRC validation
  hwmon: (sht15) add support for the status register
  hwmon: (sht15) clean-up the probe function
  hwmon: (sht15) general code clean-up
  hwmon: Add support for MAX6642
Kernel driver adm1275
=====================
Supported chips:
* Analog Devices ADM1275
Prefix: 'adm1275'
Addresses scanned: -
Datasheet: www.analog.com/static/imported-files/data_sheets/ADM1275.pdf
Author: Guenter Roeck <guenter.roeck@ericsson.com>
Description
-----------
This driver supports hardware montoring for Analog Devices ADM1275 Hot-Swap
Controller and Digital Power Monitor.
The ADM1275 is a hot-swap controller that allows a circuit board to be removed
from or inserted into a live backplane. It also features current and voltage
readback via an integrated 12-bit analog-to-digital converter (ADC), accessed
using a PMBus. interface.
The driver is a client driver to the core PMBus driver. Please see
Documentation/hwmon/pmbus for details on PMBus client drivers.
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. Please see
Documentation/hwmon/pmbus for details.
Sysfs entries
-------------
The following attributes are supported. Limits are read-write; all other
attributes are read-only.
in1_label "vin1" or "vout1" depending on chip variant and
configuration.
in1_input Measured voltage. From READ_VOUT register.
in1_min Minumum Voltage. From VOUT_UV_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_max_alarm Voltage high alarm. From VOLTAGE_OV_WARNING status.
curr1_label "iout1"
curr1_input Measured current. From READ_IOUT register.
curr1_max Maximum current. From IOUT_OC_WARN_LIMIT register.
curr1_max_alarm Current high alarm. From IOUT_OC_WARN_LIMIT register.
......@@ -15,8 +15,13 @@ Author: Rudolf Marek
Description
-----------
This driver permits reading the DTS (Digital Temperature Sensor) embedded
inside Intel CPUs. This driver can read both the per-core and per-package
temperature using the appropriate sensors. The per-package sensor is new;
as of now, it is present only in the SandyBridge platform. The driver will
show the temperature of all cores inside a package under a single device
directory inside hwmon.
This driver permits reading temperature sensor embedded inside Intel Core CPU.
Temperature is measured in degrees Celsius and measurement resolution is
1 degree C. Valid temperatures are from 0 to TjMax degrees C, because
the actual value of temperature register is in fact a delta from TjMax.
......@@ -27,13 +32,15 @@ mechanism will perform actions to forcibly cool down the processor. Alarm
may be raised, if the temperature grows enough (more than TjMax) to trigger
the Out-Of-Spec bit. Following table summarizes the exported sysfs files:
temp1_input - Core temperature (in millidegrees Celsius).
temp1_max - All cooling devices should be turned on (on Core2).
temp1_crit - Maximum junction temperature (in millidegrees Celsius).
temp1_crit_alarm - Set when Out-of-spec bit is set, never clears.
All Sysfs entries are named with their core_id (represented here by 'X').
tempX_input - Core temperature (in millidegrees Celsius).
tempX_max - All cooling devices should be turned on (on Core2).
tempX_crit - Maximum junction temperature (in millidegrees Celsius).
tempX_crit_alarm - Set when Out-of-spec bit is set, never clears.
Correct CPU operation is no longer guaranteed.
temp1_label - Contains string "Core X", where X is processor
number.
tempX_label - Contains string "Core X", where X is processor
number. For Package temp, this will be "Physical id Y",
where Y is the package number.
The TjMax temperature is set to 85 degrees C if undocumented model specific
register (UMSR) 0xee has bit 30 set. If not the TjMax is 100 degrees C as
......
Kernel driver max16065
======================
Supported chips:
* Maxim MAX16065, MAX16066
Prefixes: 'max16065', 'max16066'
Addresses scanned: -
Datasheet:
http://datasheets.maxim-ic.com/en/ds/MAX16065-MAX16066.pdf
* Maxim MAX16067
Prefix: 'max16067'
Addresses scanned: -
Datasheet:
http://datasheets.maxim-ic.com/en/ds/MAX16067.pdf
* Maxim MAX16068
Prefix: 'max16068'
Addresses scanned: -
Datasheet:
http://datasheets.maxim-ic.com/en/ds/MAX16068.pdf
* Maxim MAX16070/MAX16071
Prefixes: 'max16070', 'max16071'
Addresses scanned: -
Datasheet:
http://datasheets.maxim-ic.com/en/ds/MAX16070-MAX16071.pdf
Author: Guenter Roeck <guenter.roeck@ericsson.com>
Description
-----------
[From datasheets] The MAX16065/MAX16066 flash-configurable system managers
monitor and sequence multiple system voltages. The MAX16065/MAX16066 can also
accurately monitor (+/-2.5%) one current channel using a dedicated high-side
current-sense amplifier. The MAX16065 manages up to twelve system voltages
simultaneously, and the MAX16066 manages up to eight supply voltages.
The MAX16067 flash-configurable system manager monitors and sequences multiple
system voltages. The MAX16067 manages up to six system voltages simultaneously.
The MAX16068 flash-configurable system manager monitors and manages up to six
system voltages simultaneously.
The MAX16070/MAX16071 flash-configurable system monitors supervise multiple
system voltages. The MAX16070/MAX16071 can also accurately monitor (+/-2.5%)
one current channel using a dedicated high-side current-sense amplifier. The
MAX16070 monitors up to twelve system voltages simultaneously, and the MAX16071
monitors up to eight supply voltages.
Each monitored channel has its own low and high critical limits. MAX16065,
MAX16066, MAX16070, and MAX16071 support an additional limit which is
configurable as either low or high secondary limit. MAX16065, MAX16066,
MAX16070, and MAX16071 also support supply current monitoring.
Usage Notes
-----------
This driver does not probe for devices, since there is no register which
can be safely used to identify the chip. You will have to instantiate
the devices explicitly. Please see Documentation/i2c/instantiating-devices for
details.
Sysfs entries
-------------
in[0-11]_input Input voltage measurements.
in12_input Voltage on CSP (Current Sense Positive) pin.
Only if the chip supports current sensing and if
current sensing is enabled.
in[0-11]_min Low warning limit.
Supported on MAX16065, MAX16066, MAX16070, and MAX16071
only.
in[0-11]_max High warning limit.
Supported on MAX16065, MAX16066, MAX16070, and MAX16071
only.
Either low or high warning limits are supported
(depending on chip configuration), but not both.
in[0-11]_lcrit Low critical limit.
in[0-11]_crit High critical limit.
in[0-11]_alarm Input voltage alarm.
curr1_input Current sense input; only if the chip supports current
sensing and if current sensing is enabled.
Displayed current assumes 0.001 Ohm current sense
resistor.
curr1_alarm Overcurrent alarm; only if the chip supports current
sensing and if current sensing is enabled.
Kernel driver max6642
=====================
Supported chips:
* Maxim MAX6642
Prefix: 'max6642'
Addresses scanned: I2C 0x48-0x4f
Datasheet: Publicly available at the Maxim website
http://datasheets.maxim-ic.com/en/ds/MAX6642.pdf
Authors:
Per Dalen <per.dalen@appeartv.com>
Description
-----------
The MAX6642 is a digital temperature sensor. It senses its own temperature as
well as the temperature on one external diode.
All temperature values are given in degrees Celsius. Resolution
is 0.25 degree for the local temperature and for the remote temperature.
Kernel driver pkgtemp
======================
Supported chips:
* Intel family
Prefix: 'pkgtemp'
CPUID:
Datasheet: Intel 64 and IA-32 Architectures Software Developer's Manual
Volume 3A: System Programming Guide
Author: Fenghua Yu
Description
-----------
This driver permits reading package level temperature sensor embedded inside
Intel CPU package. The sensors can be in core, uncore, memory controller, or
other components in a package. The feature is first implemented in Intel Sandy
Bridge platform.
Temperature is measured in degrees Celsius and measurement resolution is
1 degree C. Valid temperatures are from 0 to TjMax degrees C, because the actual
value of temperature register is in fact a delta from TjMax.
Temperature known as TjMax is the maximum junction temperature of package.
We get this from MSR_IA32_TEMPERATURE_TARGET. If the MSR is not accessible,
we define TjMax as 100 degrees Celsius. At this temperature, protection
mechanism will perform actions to forcibly cool down the package. Alarm
may be raised, if the temperature grows enough (more than TjMax) to trigger
the Out-Of-Spec bit. Following table summarizes the exported sysfs files:
temp1_input - Package temperature (in millidegrees Celsius).
temp1_max - All cooling devices should be turned on.
temp1_crit - Maximum junction temperature (in millidegrees Celsius).
temp1_crit_alarm - Set when Out-of-spec bit is set, never clears.
Correct CPU operation is no longer guaranteed.
Kernel driver sht15
===================
Authors:
* Wouter Horre
* Jonathan Cameron
* Vivien Didelot <vivien.didelot@savoirfairelinux.com>
* Jerome Oufella <jerome.oufella@savoirfairelinux.com>
Supported chips:
* Sensirion SHT10
Prefix: 'sht10'
* Sensirion SHT11
Prefix: 'sht11'
* Sensirion SHT15
Prefix: 'sht15'
* Sensirion SHT71
Prefix: 'sht71'
* Sensirion SHT75
Prefix: 'sht75'
Datasheet: Publicly available at the Sensirion website
http://www.sensirion.ch/en/pdf/product_information/Datasheet-humidity-sensor-SHT1x.pdf
Description
-----------
The SHT10, SHT11, SHT15, SHT71, and SHT75 are humidity and temperature
sensors.
The devices communicate using two GPIO lines.
Supported resolutions for the measurements are 14 bits for temperature and 12
bits for humidity, or 12 bits for temperature and 8 bits for humidity.
The humidity calibration coefficients are programmed into an OTP memory on the
chip. These coefficients are used to internally calibrate the signals from the
sensors. Disabling the reload of those coefficients allows saving 10ms for each
measurement and decrease power consumption, while loosing on precision.
Some options may be set directly in the sht15_platform_data structure
or via sysfs attributes.
Notes:
* The regulator supply name is set to "vcc".
* If a CRC validation fails, a soft reset command is sent, which resets
status register to its hardware default value, but the driver will try to
restore the previous device configuration.
Platform data
-------------
* checksum:
set it to true to enable CRC validation of the readings (default to false).
* no_otp_reload:
flag to indicate not to reload from OTP (default to false).
* low_resolution:
flag to indicate the temp/humidity resolution to use (default to false).
Sysfs interface
---------------
* temp1_input: temperature input
* humidity1_input: humidity input
* heater_enable: write 1 in this attribute to enable the on-chip heater,
0 to disable it. Be careful not to enable the heater
for too long.
* temp1_fault: if 1, this means that the voltage is low (below 2.47V) and
measurement may be invalid.
* humidity1_fault: same as temp1_fault.
Kernel driver ucd9000
=====================
Supported chips:
* TI UCD90120, UCD90124, UCD9090, and UCD90910
Prefixes: 'ucd90120', 'ucd90124', 'ucd9090', 'ucd90910'
Addresses scanned: -
Datasheets:
http://focus.ti.com/lit/ds/symlink/ucd90120.pdf
http://focus.ti.com/lit/ds/symlink/ucd90124.pdf
http://focus.ti.com/lit/ds/symlink/ucd9090.pdf
http://focus.ti.com/lit/ds/symlink/ucd90910.pdf
Author: Guenter Roeck <guenter.roeck@ericsson.com>
Description
-----------
From datasheets:
The UCD90120 Power Supply Sequencer and System Health Monitor monitors and
sequences up to 12 independent voltage rails. The device integrates a 12-bit
ADC with a 2.5V internal reference for monitoring up to 13 power supply voltage,
current, or temperature inputs.
The UCD90124 is a 12-rail PMBus/I2C addressable power-supply sequencer and
system-health monitor. The device integrates a 12-bit ADC for monitoring up to
13 power-supply voltage, current, or temperature inputs. Twenty-six GPIO pins
can be used for power supply enables, power-on reset signals, external
interrupts, cascading, or other system functions. Twelve of these pins offer PWM
functionality. Using these pins, the UCD90124 offers support for fan control,
margining, and general-purpose PWM functions.
The UCD9090 is a 10-rail PMBus/I2C addressable power-supply sequencer and
monitor. The device integrates a 12-bit ADC for monitoring up to 10 power-supply
voltage inputs. Twenty-three GPIO pins can be used for power supply enables,
power-on reset signals, external interrupts, cascading, or other system
functions. Ten of these pins offer PWM functionality. Using these pins, the
UCD9090 offers support for margining, and general-purpose PWM functions.
The UCD90910 is a ten-rail I2C / PMBus addressable power-supply sequencer and
system-health monitor. The device integrates a 12-bit ADC for monitoring up to
13 power-supply voltage, current, or temperature inputs.
This 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. Please see
Documentation/hwmon/pmbus for details.
Sysfs entries
-------------
The following attributes are supported. Limits are read-write; all other
attributes are read-only.
in[1-12]_label "vout[1-12]".
in[1-12]_input Measured voltage. From READ_VOUT register.
in[1-12]_min Minumum Voltage. From VOUT_UV_WARN_LIMIT register.
in[1-12]_max Maximum voltage. From VOUT_OV_WARN_LIMIT register.
in[1-12]_lcrit Critical minumum Voltage. VOUT_UV_FAULT_LIMIT register.
in[1-12]_crit Critical maximum voltage. From VOUT_OV_FAULT_LIMIT register.
in[1-12]_min_alarm Voltage low alarm. From VOLTAGE_UV_WARNING status.
in[1-12]_max_alarm Voltage high alarm. From VOLTAGE_OV_WARNING status.
in[1-12]_lcrit_alarm Voltage critical low alarm. From VOLTAGE_UV_FAULT status.
in[1-12]_crit_alarm Voltage critical high alarm. From VOLTAGE_OV_FAULT status.
curr[1-12]_label "iout[1-12]".
curr[1-12]_input Measured current. From READ_IOUT register.
curr[1-12]_max Maximum current. From IOUT_OC_WARN_LIMIT register.
curr[1-12]_lcrit Critical minumum output current. From IOUT_UC_FAULT_LIMIT
register.
curr[1-12]_crit Critical maximum current. From IOUT_OC_FAULT_LIMIT register.
curr[1-12]_max_alarm Current high alarm. From IOUT_OC_WARNING status.
curr[1-12]_crit_alarm Current critical high alarm. From IOUT_OC_FAULT status.
For each attribute index, either voltage or current is
reported, but not both. If voltage or current is
reported depends on the chip configuration.
temp[1-2]_input Measured temperatures. From READ_TEMPERATURE_1 and
READ_TEMPERATURE_2 registers.
temp[1-2]_max Maximum temperature. From OT_WARN_LIMIT register.
temp[1-2]_crit Critical high temperature. From OT_FAULT_LIMIT register.
temp[1-2]_max_alarm Temperature high alarm.
temp[1-2]_crit_alarm Temperature critical high alarm.
fan[1-4]_input Fan RPM.
fan[1-4]_alarm Fan alarm.
fan[1-4]_fault Fan fault.
Fan attributes are only available on chips supporting
fan control (UCD90124, UCD90910). Attribute files are
created only for enabled fans.
Note that even though UCD90910 supports up to 10 fans,
only up to four fans are currently supported.
Kernel driver ucd9200
=====================
Supported chips:
* TI UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, and UCD9248
Prefixes: 'ucd9220', 'ucd9222', 'ucd9224', 'ucd9240', 'ucd9244', 'ucd9246',
'ucd9248'
Addresses scanned: -
Datasheets:
http://focus.ti.com/lit/ds/symlink/ucd9220.pdf
http://focus.ti.com/lit/ds/symlink/ucd9222.pdf
http://focus.ti.com/lit/ds/symlink/ucd9224.pdf
http://focus.ti.com/lit/ds/symlink/ucd9240.pdf
http://focus.ti.com/lit/ds/symlink/ucd9244.pdf
http://focus.ti.com/lit/ds/symlink/ucd9246.pdf
http://focus.ti.com/lit/ds/symlink/ucd9248.pdf
Author: Guenter Roeck <guenter.roeck@ericsson.com>
Description
-----------
[From datasheets] UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, and
UCD9248 are multi-rail, multi-phase synchronous buck digital PWM controllers
designed for non-isolated DC/DC power applications. The devices integrate
dedicated circuitry for DC/DC loop management with flash memory and a serial
interface to support configuration, monitoring and management.
This 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. Please see
Documentation/hwmon/pmbus for details.
Sysfs entries
-------------
The following attributes are supported. Limits are read-write; all other
attributes are read-only.
in1_label "vin".
in1_input Measured voltage. From READ_VIN register.
in1_min Minumum Voltage. From VIN_UV_WARN_LIMIT register.
in1_max Maximum voltage. From VIN_OV_WARN_LIMIT register.
in1_lcrit Critical minumum Voltage. VIN_UV_FAULT_LIMIT register.
in1_crit Critical maximum voltage. From VIN_OV_FAULT_LIMIT register.
in1_min_alarm Voltage low alarm. From VIN_UV_WARNING status.
in1_max_alarm Voltage high alarm. From VIN_OV_WARNING status.
in1_lcrit_alarm Voltage critical low alarm. From VIN_UV_FAULT status.
in1_crit_alarm Voltage critical high alarm. From VIN_OV_FAULT status.
in[2-5]_label "vout[1-4]".
in[2-5]_input Measured voltage. From READ_VOUT register.
in[2-5]_min Minumum Voltage. From VOUT_UV_WARN_LIMIT register.
in[2-5]_max Maximum voltage. From VOUT_OV_WARN_LIMIT register.
in[2-5]_lcrit Critical minumum Voltage. VOUT_UV_FAULT_LIMIT register.
in[2-5]_crit Critical maximum voltage. From VOUT_OV_FAULT_LIMIT register.
in[2-5]_min_alarm Voltage low alarm. From VOLTAGE_UV_WARNING status.
in[2-5]_max_alarm Voltage high alarm. From VOLTAGE_OV_WARNING status.
in[2-5]_lcrit_alarm Voltage critical low alarm. From VOLTAGE_UV_FAULT status.
in[2-5]_crit_alarm Voltage critical high alarm. From VOLTAGE_OV_FAULT status.
curr1_label "iin".
curr1_input Measured current. From READ_IIN register.
curr[2-5]_label "iout[1-4]".
curr[2-5]_input Measured current. From READ_IOUT register.
curr[2-5]_max Maximum current. From IOUT_OC_WARN_LIMIT register.
curr[2-5]_lcrit Critical minumum output current. From IOUT_UC_FAULT_LIMIT
register.
curr[2-5]_crit Critical maximum current. From IOUT_OC_FAULT_LIMIT register.
curr[2-5]_max_alarm Current high alarm. From IOUT_OC_WARNING status.
curr[2-5]_crit_alarm Current critical high alarm. From IOUT_OC_FAULT status.
power1_input Measured input power. From READ_PIN register.
power1_label "pin"
power[2-5]_input Measured output power. From READ_POUT register.
power[2-5]_label "pout[1-4]"
The number of output voltage, current, and power
attribute sets is determined by the number of enabled
rails. See chip datasheets for details.
temp[1-5]_input Measured temperatures. From READ_TEMPERATURE_1 and
READ_TEMPERATURE_2 registers.
temp1 is the chip internal temperature. temp[2-5] are
rail temperatures. temp[2-5] attributes are only
created for enabled rails. See chip datasheets for
details.
temp[1-5]_max Maximum temperature. From OT_WARN_LIMIT register.
temp[1-5]_crit Critical high temperature. From OT_FAULT_LIMIT register.
temp[1-5]_max_alarm Temperature high alarm.
temp[1-5]_crit_alarm Temperature critical high alarm.
fan1_input Fan RPM. ucd9240 only.
fan1_alarm Fan alarm. ucd9240 only.
fan1_fault Fan fault. ucd9240 only.
......@@ -408,13 +408,6 @@ config SENSORS_CORETEMP
sensor inside your CPU. Most of the family 6 CPUs
are supported. Check Documentation/hwmon/coretemp for details.
config SENSORS_PKGTEMP
tristate "Intel processor package temperature sensor"
depends on X86 && EXPERIMENTAL
help
If you say yes here you get support for the package level temperature
sensor inside your CPU. Check documentation/driver for details.
config SENSORS_IBMAEM
tristate "IBM Active Energy Manager temperature/power sensors and control"
select IPMI_SI
......@@ -708,6 +701,22 @@ config SENSORS_MAX1111
This driver can also be built as a module. If so, the module
will be called max1111.
config SENSORS_MAX16065
tristate "Maxim MAX16065 System Manager and compatibles"
depends on I2C
help
If you say yes here you get support for hardware monitoring
capabilities of the following Maxim System Manager chips.
MAX16065
MAX16066
MAX16067
MAX16068
MAX16070
MAX16071
This driver can also be built as a module. If so, the module
will be called max16065.
config SENSORS_MAX1619
tristate "Maxim MAX1619 sensor chip"
depends on I2C
......@@ -727,6 +736,17 @@ config SENSORS_MAX6639
This driver can also be built as a module. If so, the module
will be called max6639.
config SENSORS_MAX6642
tristate "Maxim MAX6642 sensor chip"
depends on I2C && EXPERIMENTAL
help
If you say yes here you get support for MAX6642 sensor chip.
MAX6642 is a SMBus-Compatible Remote/Local Temperature Sensor
with Overtemperature Alarm from Maxim.
This driver can also be built as a module. If so, the module
will be called max6642.
config SENSORS_MAX6650
tristate "Maxim MAX6650 sensor chip"
depends on I2C && EXPERIMENTAL
......@@ -800,6 +820,16 @@ config SENSORS_PMBUS
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
......@@ -830,6 +860,28 @@ config SENSORS_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
......
......@@ -40,7 +40,6 @@ obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o
obj-$(CONFIG_SENSORS_ASC7621) += asc7621.o
obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
obj-$(CONFIG_SENSORS_PKGTEMP) += pkgtemp.o
obj-$(CONFIG_SENSORS_DME1737) += dme1737.o
obj-$(CONFIG_SENSORS_DS620) += ds620.o
obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
......@@ -83,8 +82,10 @@ obj-$(CONFIG_SENSORS_LTC4215) += ltc4215.o
obj-$(CONFIG_SENSORS_LTC4245) += ltc4245.o
obj-$(CONFIG_SENSORS_LTC4261) += ltc4261.o
obj-$(CONFIG_SENSORS_MAX1111) += max1111.o
obj-$(CONFIG_SENSORS_MAX16065) += max16065.o
obj-$(CONFIG_SENSORS_MAX1619) += max1619.o
obj-$(CONFIG_SENSORS_MAX6639) += max6639.o
obj-$(CONFIG_SENSORS_MAX6642) += max6642.o
obj-$(CONFIG_SENSORS_MAX6650) += max6650.o
obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
......@@ -118,9 +119,12 @@ obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o
# PMBus drivers
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
/*
* Hardware monitoring driver for Analog Devices ADM1275 Hot-Swap Controller
* and Digital Power Monitor
*
* 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.
*/
#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"
#define ADM1275_PMON_CONFIG 0xd4
#define ADM1275_VIN_VOUT_SELECT (1 << 6)
#define ADM1275_VRANGE (1 << 5)
static int adm1275_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int config;
struct pmbus_driver_info *info;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_READ_BYTE_DATA))
return -ENODEV;
info = kzalloc(sizeof(struct pmbus_driver_info), GFP_KERNEL);
if (!info)
return -ENOMEM;
config = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG);
if (config < 0)
return config;
info->pages = 1;
info->direct[PSC_VOLTAGE_IN] = true;
info->direct[PSC_VOLTAGE_OUT] = true;
info->direct[PSC_CURRENT_OUT] = true;
info->m[PSC_CURRENT_OUT] = 800;
info->b[PSC_CURRENT_OUT] = 20475;
info->R[PSC_CURRENT_OUT] = -1;
info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
if (config & ADM1275_VRANGE) {
info->m[PSC_VOLTAGE_IN] = 19045;
info->b[PSC_VOLTAGE_IN] = 0;
info->R[PSC_VOLTAGE_IN] = -2;
info->m[PSC_VOLTAGE_OUT] = 19045;
info->b[PSC_VOLTAGE_OUT] = 0;
info->R[PSC_VOLTAGE_OUT] = -2;
} else {
info->m[PSC_VOLTAGE_IN] = 6666;
info->b[PSC_VOLTAGE_IN] = 0;
info->R[PSC_VOLTAGE_IN] = -1;
info->m[PSC_VOLTAGE_OUT] = 6666;
info->b[PSC_VOLTAGE_OUT] = 0;
info->R[PSC_VOLTAGE_OUT] = -1;
}
if (config & ADM1275_VIN_VOUT_SELECT)
info->func[0] |= PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
else
info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT;
return pmbus_do_probe(client, id, info);
}
static int adm1275_remove(struct i2c_client *client)
{
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
int ret;
ret = pmbus_do_remove(client);
kfree(info);
return ret;
}
static const struct i2c_device_id adm1275_id[] = {
{"adm1275", 0},
{ }
};
MODULE_DEVICE_TABLE(i2c, adm1275_id);
static struct i2c_driver adm1275_driver = {
.driver = {
.name = "adm1275",
},
.probe = adm1275_probe,
.remove = adm1275_remove,
.id_table = adm1275_id,
};
static int __init adm1275_init(void)
{
return i2c_add_driver(&adm1275_driver);
}
static void __exit adm1275_exit(void)
{
i2c_del_driver(&adm1275_driver);
}
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for Analog Devices ADM1275");
MODULE_LICENSE("GPL");
module_init(adm1275_init);
module_exit(adm1275_exit);
此差异已折叠。
此差异已折叠。
......@@ -32,7 +32,7 @@ enum chips { max34440, max34441 };
#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)
static int max34440_read_byte_data(struct i2c_client *client, int page, int reg)
{
int ret;
int mfg_status;
......@@ -108,7 +108,7 @@ static struct pmbus_driver_info max34440_info[] = {
.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,
.read_byte_data = max34440_read_byte_data,
},
[max34441] = {
.pages = 12,
......@@ -149,7 +149,7 @@ static struct pmbus_driver_info max34440_info[] = {
.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,
.read_byte_data = max34440_read_byte_data,
},
};
......
/*
* Driver for +/-1 degree C, SMBus-Compatible Remote/Local Temperature Sensor
* with Overtemperature Alarm
*
* Copyright (C) 2011 AppearTV AS
*
* Derived from:
*
* Based on the max1619 driver.
* Copyright (C) 2003-2004 Alexey Fisher <fishor@mail.ru>
* Jean Delvare <khali@linux-fr.org>
*
* The MAX6642 is a sensor chip made by Maxim.
* It reports up to two temperatures (its own plus up to
* one external one). Complete datasheet can be
* obtained from Maxim's website at:
* http://datasheets.maxim-ic.com/en/ds/MAX6642.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/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
static const unsigned short normal_i2c[] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
/*
* The MAX6642 registers
*/
#define MAX6642_REG_R_MAN_ID 0xFE
#define MAX6642_REG_R_CONFIG 0x03
#define MAX6642_REG_W_CONFIG 0x09
#define MAX6642_REG_R_STATUS 0x02
#define MAX6642_REG_R_LOCAL_TEMP 0x00
#define MAX6642_REG_R_LOCAL_TEMPL 0x11
#define MAX6642_REG_R_LOCAL_HIGH 0x05
#define MAX6642_REG_W_LOCAL_HIGH 0x0B
#define MAX6642_REG_R_REMOTE_TEMP 0x01
#define MAX6642_REG_R_REMOTE_TEMPL 0x10
#define MAX6642_REG_R_REMOTE_HIGH 0x07
#define MAX6642_REG_W_REMOTE_HIGH 0x0D
/*
* Conversions
*/
static int temp_from_reg10(int val)
{
return val * 250;
}
static int temp_from_reg(int val)
{
return val * 1000;
}
static int temp_to_reg(int val)
{
return val / 1000;
}
/*
* Client data (each client gets its own)
*/
struct max6642_data {
struct device *hwmon_dev;
struct mutex update_lock;
bool valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
/* registers values */
u16 temp_input[2]; /* local/remote */
u16 temp_high[2]; /* local/remote */
u8 alarms;
};
/*
* Real code
*/
static void max6642_init_client(struct i2c_client *client)
{
u8 config;
struct max6642_data *data = i2c_get_clientdata(client);
/*
* Start the conversions.
*/
config = i2c_smbus_read_byte_data(client, MAX6642_REG_R_CONFIG);
if (config & 0x40)
i2c_smbus_write_byte_data(client, MAX6642_REG_W_CONFIG,
config & 0xBF); /* run */
data->temp_high[0] = i2c_smbus_read_byte_data(client,
MAX6642_REG_R_LOCAL_HIGH);
data->temp_high[1] = i2c_smbus_read_byte_data(client,
MAX6642_REG_R_REMOTE_HIGH);
}
/* Return 0 if detection is successful, -ENODEV otherwise */
static int max6642_detect(struct i2c_client *client,
struct i2c_board_info *info)
{
struct i2c_adapter *adapter = client->adapter;
u8 reg_config, reg_status, man_id;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV;
/* identification */
man_id = i2c_smbus_read_byte_data(client, MAX6642_REG_R_MAN_ID);
if (man_id != 0x4D)
return -ENODEV;
/*
* We read the config and status register, the 4 lower bits in the
* config register should be zero and bit 5, 3, 1 and 0 should be
* zero in the status register.
*/
reg_config = i2c_smbus_read_byte_data(client, MAX6642_REG_R_CONFIG);
reg_status = i2c_smbus_read_byte_data(client, MAX6642_REG_R_STATUS);
if (((reg_config & 0x0f) != 0x00) ||
((reg_status & 0x2b) != 0x00))
return -ENODEV;
strlcpy(info->type, "max6642", I2C_NAME_SIZE);
return 0;
}
static struct max6642_data *max6642_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct max6642_data *data = i2c_get_clientdata(client);
u16 val, tmp;
mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
dev_dbg(&client->dev, "Updating max6642 data.\n");
val = i2c_smbus_read_byte_data(client,
MAX6642_REG_R_LOCAL_TEMPL);
tmp = (val >> 6) & 3;
val = i2c_smbus_read_byte_data(client,
MAX6642_REG_R_LOCAL_TEMP);
val = (val << 2) | tmp;
data->temp_input[0] = val;
val = i2c_smbus_read_byte_data(client,
MAX6642_REG_R_REMOTE_TEMPL);
tmp = (val >> 6) & 3;
val = i2c_smbus_read_byte_data(client,
MAX6642_REG_R_REMOTE_TEMP);
val = (val << 2) | tmp;
data->temp_input[1] = val;
data->alarms = i2c_smbus_read_byte_data(client,
MAX6642_REG_R_STATUS);
data->last_updated = jiffies;
data->valid = 1;
}
mutex_unlock(&data->update_lock);
return data;
}
/*
* Sysfs stuff
*/
static ssize_t show_temp_max10(struct device *dev,
struct device_attribute *dev_attr, char *buf)
{
struct max6642_data *data = max6642_update_device(dev);
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
return sprintf(buf, "%d\n",
temp_from_reg10(data->temp_input[attr->index]));
}
static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct max6642_data *data = max6642_update_device(dev);
struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr);
return sprintf(buf, "%d\n", temp_from_reg(data->temp_high[attr2->nr]));
}
static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
unsigned long val;
int err;
struct i2c_client *client = to_i2c_client(dev);
struct max6642_data *data = i2c_get_clientdata(client);
struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr);
err = strict_strtoul(buf, 10, &val);
if (err < 0)
return err;
mutex_lock(&data->update_lock);
data->temp_high[attr2->nr] = SENSORS_LIMIT(temp_to_reg(val), 0, 255);
i2c_smbus_write_byte_data(client, attr2->index,
data->temp_high[attr2->nr]);
mutex_unlock(&data->update_lock);
return count;
}
static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
char *buf)
{
int bitnr = to_sensor_dev_attr(attr)->index;
struct max6642_data *data = max6642_update_device(dev);
return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1);
}
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_max10, NULL, 0);
static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_max10, NULL, 1);
static SENSOR_DEVICE_ATTR_2(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
set_temp_max, 0, MAX6642_REG_W_LOCAL_HIGH);
static SENSOR_DEVICE_ATTR_2(temp2_max, S_IWUSR | S_IRUGO, show_temp_max,
set_temp_max, 1, MAX6642_REG_W_REMOTE_HIGH);
static SENSOR_DEVICE_ATTR(temp_fault, S_IRUGO, show_alarm, NULL, 2);
static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4);
static struct attribute *max6642_attributes[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp2_input.dev_attr.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr,
&sensor_dev_attr_temp2_max.dev_attr.attr,
&sensor_dev_attr_temp_fault.dev_attr.attr,
&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
NULL
};
static const struct attribute_group max6642_group = {
.attrs = max6642_attributes,
};
static int max6642_probe(struct i2c_client *new_client,
const struct i2c_device_id *id)
{
struct max6642_data *data;
int err;
data = kzalloc(sizeof(struct max6642_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
}
i2c_set_clientdata(new_client, data);
mutex_init(&data->update_lock);
/* Initialize the MAX6642 chip */
max6642_init_client(new_client);
/* Register sysfs hooks */
err = sysfs_create_group(&new_client->dev.kobj, &max6642_group);
if (err)
goto exit_free;
data->hwmon_dev = hwmon_device_register(&new_client->dev);
if (IS_ERR(data->hwmon_dev)) {
err = PTR_ERR(data->hwmon_dev);
goto exit_remove_files;
}
return 0;
exit_remove_files:
sysfs_remove_group(&new_client->dev.kobj, &max6642_group);
exit_free:
kfree(data);
exit:
return err;
}
static int max6642_remove(struct i2c_client *client)
{
struct max6642_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &max6642_group);
kfree(data);
return 0;
}
/*
* Driver data (common to all clients)
*/
static const struct i2c_device_id max6642_id[] = {
{ "max6642", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, max6642_id);
static struct i2c_driver max6642_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = "max6642",
},
.probe = max6642_probe,
.remove = max6642_remove,
.id_table = max6642_id,
.detect = max6642_detect,
.address_list = normal_i2c,
};
static int __init max6642_init(void)
{
return i2c_add_driver(&max6642_driver);
}
static void __exit max6642_exit(void)
{
i2c_del_driver(&max6642_driver);
}
MODULE_AUTHOR("Per Dalen <per.dalen@appeartv.com>");
MODULE_DESCRIPTION("MAX6642 sensor driver");
MODULE_LICENSE("GPL");
module_init(max6642_init);
module_exit(max6642_exit);
......@@ -37,7 +37,7 @@
#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)
static int max8688_read_byte_data(struct i2c_client *client, int page, int reg)
{
int ret = 0;
int mfg_status;
......@@ -110,7 +110,7 @@ static struct pmbus_driver_info max8688_info = {
.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,
.read_byte_data = max8688_read_byte_data,
};
static int max8688_probe(struct i2c_client *client,
......
/*
* pkgtemp.c - Linux kernel module for processor package hardware monitoring
*
* Copyright (C) 2010 Fenghua Yu <fenghua.yu@intel.com>
*
* Inspired from many hwmon drivers especially coretemp.
*
* 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; version 2 of the License.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/hwmon.h>
#include <linux/sysfs.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/list.h>
#include <linux/platform_device.h>
#include <linux/cpu.h>
#include <asm/msr.h>
#include <asm/processor.h>
#include <asm/smp.h>
#define DRVNAME "pkgtemp"
enum { SHOW_TEMP, SHOW_TJMAX, SHOW_TTARGET, SHOW_LABEL, SHOW_NAME };
/*
* Functions declaration
*/
static struct pkgtemp_data *pkgtemp_update_device(struct device *dev);
struct pkgtemp_data {
struct device *hwmon_dev;
struct mutex update_lock;
const char *name;
u32 id;
u16 phys_proc_id;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
int temp;
int tjmax;
int ttarget;
u8 alarm;
};
/*
* Sysfs stuff
*/
static ssize_t show_name(struct device *dev, struct device_attribute
*devattr, char *buf)
{
int ret;
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct pkgtemp_data *data = dev_get_drvdata(dev);
if (attr->index == SHOW_NAME)
ret = sprintf(buf, "%s\n", data->name);
else /* show label */
ret = sprintf(buf, "physical id %d\n",
data->phys_proc_id);
return ret;
}
static ssize_t show_alarm(struct device *dev, struct device_attribute
*devattr, char *buf)
{
struct pkgtemp_data *data = pkgtemp_update_device(dev);
/* read the Out-of-spec log, never clear */
return sprintf(buf, "%d\n", data->alarm);
}
static ssize_t show_temp(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct pkgtemp_data *data = pkgtemp_update_device(dev);
int err = 0;
if (attr->index == SHOW_TEMP)
err = data->valid ? sprintf(buf, "%d\n", data->temp) : -EAGAIN;
else if (attr->index == SHOW_TJMAX)
err = sprintf(buf, "%d\n", data->tjmax);
else
err = sprintf(buf, "%d\n", data->ttarget);
return err;
}
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, SHOW_TEMP);
static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp, NULL, SHOW_TJMAX);
static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL, SHOW_TTARGET);
static DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL);
static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL);
static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, SHOW_NAME);
static struct attribute *pkgtemp_attributes[] = {
&sensor_dev_attr_name.dev_attr.attr,
&sensor_dev_attr_temp1_label.dev_attr.attr,
&dev_attr_temp1_crit_alarm.attr,
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp1_crit.dev_attr.attr,
NULL
};
static const struct attribute_group pkgtemp_group = {
.attrs = pkgtemp_attributes,
};
static struct pkgtemp_data *pkgtemp_update_device(struct device *dev)
{
struct pkgtemp_data *data = dev_get_drvdata(dev);
unsigned int cpu;
int err;
mutex_lock(&data->update_lock);
if (!data->valid || time_after(jiffies, data->last_updated + HZ)) {
u32 eax, edx;
data->valid = 0;
cpu = data->id;
err = rdmsr_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_STATUS,
&eax, &edx);
if (!err) {
data->alarm = (eax >> 5) & 1;
data->temp = data->tjmax - (((eax >> 16)
& 0x7f) * 1000);
data->valid = 1;
} else
dev_dbg(dev, "Temperature data invalid (0x%x)\n", eax);
data->last_updated = jiffies;
}
mutex_unlock(&data->update_lock);
return data;
}
static int get_tjmax(int cpu, struct device *dev)
{
int default_tjmax = 100000;
int err;
u32 eax, edx;
u32 val;
/* IA32_TEMPERATURE_TARGET contains the TjMax value */
err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
if (!err) {
val = (eax >> 16) & 0xff;
if ((val > 80) && (val < 120)) {
dev_info(dev, "TjMax is %d C.\n", val);
return val * 1000;
}
}
dev_warn(dev, "Unable to read TjMax from CPU.\n");
return default_tjmax;
}
static int __devinit pkgtemp_probe(struct platform_device *pdev)
{
struct pkgtemp_data *data;
int err;
u32 eax, edx;
#ifdef CONFIG_SMP
struct cpuinfo_x86 *c = &cpu_data(pdev->id);
#endif
data = kzalloc(sizeof(struct pkgtemp_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
dev_err(&pdev->dev, "Out of memory\n");
goto exit;
}
data->id = pdev->id;
#ifdef CONFIG_SMP
data->phys_proc_id = c->phys_proc_id;
#endif
data->name = "pkgtemp";
mutex_init(&data->update_lock);
/* test if we can access the THERM_STATUS MSR */
err = rdmsr_safe_on_cpu(data->id, MSR_IA32_PACKAGE_THERM_STATUS,
&eax, &edx);
if (err) {
dev_err(&pdev->dev,
"Unable to access THERM_STATUS MSR, giving up\n");
goto exit_free;
}
data->tjmax = get_tjmax(data->id, &pdev->dev);
platform_set_drvdata(pdev, data);
err = rdmsr_safe_on_cpu(data->id, MSR_IA32_TEMPERATURE_TARGET,
&eax, &edx);
if (err) {
dev_warn(&pdev->dev, "Unable to read"
" IA32_TEMPERATURE_TARGET MSR\n");
} else {
data->ttarget = data->tjmax - (((eax >> 8) & 0xff) * 1000);
err = device_create_file(&pdev->dev,
&sensor_dev_attr_temp1_max.dev_attr);
if (err)
goto exit_free;
}
err = sysfs_create_group(&pdev->dev.kobj, &pkgtemp_group);
if (err)
goto exit_dev;
data->hwmon_dev = hwmon_device_register(&pdev->dev);
if (IS_ERR(data->hwmon_dev)) {
err = PTR_ERR(data->hwmon_dev);
dev_err(&pdev->dev, "Class registration failed (%d)\n",
err);
goto exit_class;
}
return 0;
exit_class:
sysfs_remove_group(&pdev->dev.kobj, &pkgtemp_group);
exit_dev:
device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr);
exit_free:
kfree(data);
exit:
return err;
}
static int __devexit pkgtemp_remove(struct platform_device *pdev)
{
struct pkgtemp_data *data = platform_get_drvdata(pdev);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&pdev->dev.kobj, &pkgtemp_group);
device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr);
platform_set_drvdata(pdev, NULL);
kfree(data);
return 0;
}
static struct platform_driver pkgtemp_driver = {
.driver = {
.owner = THIS_MODULE,
.name = DRVNAME,
},
.probe = pkgtemp_probe,
.remove = __devexit_p(pkgtemp_remove),
};
struct pdev_entry {
struct list_head list;
struct platform_device *pdev;
unsigned int cpu;
#ifdef CONFIG_SMP
u16 phys_proc_id;
#endif
};
static LIST_HEAD(pdev_list);
static DEFINE_MUTEX(pdev_list_mutex);
static int __cpuinit pkgtemp_device_add(unsigned int cpu)
{
int err;
struct platform_device *pdev;
struct pdev_entry *pdev_entry;
struct cpuinfo_x86 *c = &cpu_data(cpu);
if (!cpu_has(c, X86_FEATURE_PTS))
return 0;
mutex_lock(&pdev_list_mutex);
#ifdef CONFIG_SMP
/* Only keep the first entry in each package */
list_for_each_entry(pdev_entry, &pdev_list, list) {
if (c->phys_proc_id == pdev_entry->phys_proc_id) {
err = 0; /* Not an error */
goto exit;
}
}
#endif
pdev = platform_device_alloc(DRVNAME, cpu);
if (!pdev) {
err = -ENOMEM;
pr_err("Device allocation failed\n");
goto exit;
}
pdev_entry = kzalloc(sizeof(struct pdev_entry), GFP_KERNEL);
if (!pdev_entry) {
err = -ENOMEM;
goto exit_device_put;
}
err = platform_device_add(pdev);
if (err) {
pr_err("Device addition failed (%d)\n", err);
goto exit_device_free;
}
#ifdef CONFIG_SMP
pdev_entry->phys_proc_id = c->phys_proc_id;
#endif
pdev_entry->pdev = pdev;
pdev_entry->cpu = cpu;
list_add_tail(&pdev_entry->list, &pdev_list);
mutex_unlock(&pdev_list_mutex);
return 0;
exit_device_free:
kfree(pdev_entry);
exit_device_put:
platform_device_put(pdev);
exit:
mutex_unlock(&pdev_list_mutex);
return err;
}
static void __cpuinit pkgtemp_device_remove(unsigned int cpu)
{
struct pdev_entry *p;
unsigned int i;
int err;
mutex_lock(&pdev_list_mutex);
list_for_each_entry(p, &pdev_list, list) {
if (p->cpu != cpu)
continue;
platform_device_unregister(p->pdev);
list_del(&p->list);
mutex_unlock(&pdev_list_mutex);
kfree(p);
for_each_cpu(i, cpu_core_mask(cpu)) {
if (i != cpu) {
err = pkgtemp_device_add(i);
if (!err)
break;
}
}
return;
}
mutex_unlock(&pdev_list_mutex);
}
static int __cpuinit pkgtemp_cpu_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long) hcpu;
switch (action) {
case CPU_ONLINE:
case CPU_DOWN_FAILED:
pkgtemp_device_add(cpu);
break;
case CPU_DOWN_PREPARE:
pkgtemp_device_remove(cpu);
break;
}
return NOTIFY_OK;
}
static struct notifier_block pkgtemp_cpu_notifier __refdata = {
.notifier_call = pkgtemp_cpu_callback,
};
static int __init pkgtemp_init(void)
{
int i, err = -ENODEV;
/* quick check if we run Intel */
if (cpu_data(0).x86_vendor != X86_VENDOR_INTEL)
goto exit;
err = platform_driver_register(&pkgtemp_driver);
if (err)
goto exit;
for_each_online_cpu(i)
pkgtemp_device_add(i);
#ifndef CONFIG_HOTPLUG_CPU
if (list_empty(&pdev_list)) {
err = -ENODEV;
goto exit_driver_unreg;
}
#endif
register_hotcpu_notifier(&pkgtemp_cpu_notifier);
return 0;
#ifndef CONFIG_HOTPLUG_CPU
exit_driver_unreg:
platform_driver_unregister(&pkgtemp_driver);
#endif
exit:
return err;
}
static void __exit pkgtemp_exit(void)
{
struct pdev_entry *p, *n;
unregister_hotcpu_notifier(&pkgtemp_cpu_notifier);
mutex_lock(&pdev_list_mutex);
list_for_each_entry_safe(p, n, &pdev_list, list) {
platform_device_unregister(p->pdev);
list_del(&p->list);
kfree(p);
}
mutex_unlock(&pdev_list_mutex);
platform_driver_unregister(&pkgtemp_driver);
}
MODULE_AUTHOR("Fenghua Yu <fenghua.yu@intel.com>");
MODULE_DESCRIPTION("Intel processor package temperature monitor");
MODULE_LICENSE("GPL");
module_init(pkgtemp_init)
module_exit(pkgtemp_exit)
......@@ -281,13 +281,11 @@ struct pmbus_driver_info {
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.
* The following functions map manufacturing specific register values
* to PMBus standard register values. Specify only if mapping is
* necessary.
*/
int (*get_status)(struct i2c_client *client, int page, int reg);
int (*read_byte_data)(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
......
此差异已折叠。
此差异已折叠。
/*
* Hardware monitoring driver for UCD90xxx Sequencer and System Health
* Controller series
*
* 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 <linux/i2c/pmbus.h>
#include "pmbus.h"
enum chips { ucd9000, ucd90120, ucd90124, ucd9090, ucd90910 };
#define UCD9000_MONITOR_CONFIG 0xd5
#define UCD9000_NUM_PAGES 0xd6
#define UCD9000_FAN_CONFIG_INDEX 0xe7
#define UCD9000_FAN_CONFIG 0xe8
#define UCD9000_DEVICE_ID 0xfd
#define UCD9000_MON_TYPE(x) (((x) >> 5) & 0x07)
#define UCD9000_MON_PAGE(x) ((x) & 0x0f)
#define UCD9000_MON_VOLTAGE 1
#define UCD9000_MON_TEMPERATURE 2
#define UCD9000_MON_CURRENT 3
#define UCD9000_MON_VOLTAGE_HW 4
#define UCD9000_NUM_FAN 4
struct ucd9000_data {
u8 fan_data[UCD9000_NUM_FAN][I2C_SMBUS_BLOCK_MAX];
struct pmbus_driver_info info;
};
#define to_ucd9000_data(_info) container_of(_info, struct ucd9000_data, info)
static int ucd9000_get_fan_config(struct i2c_client *client, int fan)
{
int fan_config = 0;
struct ucd9000_data *data
= to_ucd9000_data(pmbus_get_driver_info(client));
if (data->fan_data[fan][3] & 1)
fan_config |= PB_FAN_2_INSTALLED; /* Use lower bit position */
/* Pulses/revolution */
fan_config |= (data->fan_data[fan][3] & 0x06) >> 1;
return fan_config;
}
static int ucd9000_read_byte_data(struct i2c_client *client, int page, int reg)
{
int ret = 0;
int fan_config;
switch (reg) {
case PMBUS_FAN_CONFIG_12:
if (page)
return -EINVAL;
ret = ucd9000_get_fan_config(client, 0);
if (ret < 0)
return ret;
fan_config = ret << 4;
ret = ucd9000_get_fan_config(client, 1);
if (ret < 0)
return ret;
fan_config |= ret;
ret = fan_config;
break;
case PMBUS_FAN_CONFIG_34:
if (page)
return -EINVAL;
ret = ucd9000_get_fan_config(client, 2);
if (ret < 0)
return ret;
fan_config = ret << 4;
ret = ucd9000_get_fan_config(client, 3);
if (ret < 0)
return ret;
fan_config |= ret;
ret = fan_config;
break;
default:
ret = -ENODATA;
break;
}
return ret;
}
static const struct i2c_device_id ucd9000_id[] = {
{"ucd9000", ucd9000},
{"ucd90120", ucd90120},
{"ucd90124", ucd90124},
{"ucd9090", ucd9090},
{"ucd90910", ucd90910},
{}
};
MODULE_DEVICE_TABLE(i2c, ucd9000_id);
static int ucd9000_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1];
struct ucd9000_data *data;
struct pmbus_driver_info *info;
const struct i2c_device_id *mid;
int i, ret;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_BLOCK_DATA))
return -ENODEV;
ret = i2c_smbus_read_block_data(client, UCD9000_DEVICE_ID,
block_buffer);
if (ret < 0) {
dev_err(&client->dev, "Failed to read device ID\n");
return ret;
}
block_buffer[ret] = '\0';
dev_info(&client->dev, "Device ID %s\n", block_buffer);
mid = NULL;
for (i = 0; i < ARRAY_SIZE(ucd9000_id); i++) {
mid = &ucd9000_id[i];
if (!strncasecmp(mid->name, block_buffer, strlen(mid->name)))
break;
}
if (!mid || !strlen(mid->name)) {
dev_err(&client->dev, "Unsupported device\n");
return -ENODEV;
}
if (id->driver_data != ucd9000 && id->driver_data != mid->driver_data)
dev_notice(&client->dev,
"Device mismatch: Configured %s, detected %s\n",
id->name, mid->name);
data = kzalloc(sizeof(struct ucd9000_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
info = &data->info;
ret = i2c_smbus_read_byte_data(client, UCD9000_NUM_PAGES);
if (ret < 0) {
dev_err(&client->dev,
"Failed to read number of active pages\n");
goto out;
}
info->pages = ret;
if (!info->pages) {
dev_err(&client->dev, "No pages configured\n");
ret = -ENODEV;
goto out;
}
/* The internal temperature sensor is always active */
info->func[0] = PMBUS_HAVE_TEMP;
/* Everything else is configurable */
ret = i2c_smbus_read_block_data(client, UCD9000_MONITOR_CONFIG,
block_buffer);
if (ret <= 0) {
dev_err(&client->dev, "Failed to read configuration data\n");
ret = -ENODEV;
goto out;
}
for (i = 0; i < ret; i++) {
int page = UCD9000_MON_PAGE(block_buffer[i]);
if (page >= info->pages)
continue;
switch (UCD9000_MON_TYPE(block_buffer[i])) {
case UCD9000_MON_VOLTAGE:
case UCD9000_MON_VOLTAGE_HW:
info->func[page] |= PMBUS_HAVE_VOUT
| PMBUS_HAVE_STATUS_VOUT;
break;
case UCD9000_MON_TEMPERATURE:
info->func[page] |= PMBUS_HAVE_TEMP2
| PMBUS_HAVE_STATUS_TEMP;
break;
case UCD9000_MON_CURRENT:
info->func[page] |= PMBUS_HAVE_IOUT
| PMBUS_HAVE_STATUS_IOUT;
break;
default:
break;
}
}
/* Fan configuration */
if (mid->driver_data == ucd90124) {
for (i = 0; i < UCD9000_NUM_FAN; i++) {
i2c_smbus_write_byte_data(client,
UCD9000_FAN_CONFIG_INDEX, i);
ret = i2c_smbus_read_block_data(client,
UCD9000_FAN_CONFIG,
data->fan_data[i]);
if (ret < 0)
goto out;
}
i2c_smbus_write_byte_data(client, UCD9000_FAN_CONFIG_INDEX, 0);
info->read_byte_data = ucd9000_read_byte_data;
info->func[0] |= PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12
| PMBUS_HAVE_FAN34 | PMBUS_HAVE_STATUS_FAN34;
}
ret = pmbus_do_probe(client, mid, info);
if (ret < 0)
goto out;
return 0;
out:
kfree(data);
return ret;
}
static int ucd9000_remove(struct i2c_client *client)
{
int ret;
struct ucd9000_data *data;
data = to_ucd9000_data(pmbus_get_driver_info(client));
ret = pmbus_do_remove(client);
kfree(data);
return ret;
}
/* This is the driver that will be inserted */
static struct i2c_driver ucd9000_driver = {
.driver = {
.name = "ucd9000",
},
.probe = ucd9000_probe,
.remove = ucd9000_remove,
.id_table = ucd9000_id,
};
static int __init ucd9000_init(void)
{
return i2c_add_driver(&ucd9000_driver);
}
static void __exit ucd9000_exit(void)
{
i2c_del_driver(&ucd9000_driver);
}
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for TI UCD90xxx");
MODULE_LICENSE("GPL");
module_init(ucd9000_init);
module_exit(ucd9000_exit);
/*
* Hardware monitoring driver for ucd9200 series Digital PWM System Controllers
*
* 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 <linux/i2c/pmbus.h>
#include "pmbus.h"
#define UCD9200_PHASE_INFO 0xd2
#define UCD9200_DEVICE_ID 0xfd
enum chips { ucd9200, ucd9220, ucd9222, ucd9224, ucd9240, ucd9244, ucd9246,
ucd9248 };
static const struct i2c_device_id ucd9200_id[] = {
{"ucd9200", ucd9200},
{"ucd9220", ucd9220},
{"ucd9222", ucd9222},
{"ucd9224", ucd9224},
{"ucd9240", ucd9240},
{"ucd9244", ucd9244},
{"ucd9246", ucd9246},
{"ucd9248", ucd9248},
{}
};
MODULE_DEVICE_TABLE(i2c, ucd9200_id);
static int ucd9200_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1];
struct pmbus_driver_info *info;
const struct i2c_device_id *mid;
int i, j, ret;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_BLOCK_DATA))
return -ENODEV;
ret = i2c_smbus_read_block_data(client, UCD9200_DEVICE_ID,
block_buffer);
if (ret < 0) {
dev_err(&client->dev, "Failed to read device ID\n");
return ret;
}
block_buffer[ret] = '\0';
dev_info(&client->dev, "Device ID %s\n", block_buffer);
mid = NULL;
for (i = 0; i < ARRAY_SIZE(ucd9200_id); i++) {
mid = &ucd9200_id[i];
if (!strncasecmp(mid->name, block_buffer, strlen(mid->name)))
break;
}
if (!mid || !strlen(mid->name)) {
dev_err(&client->dev, "Unsupported device\n");
return -ENODEV;
}
if (id->driver_data != ucd9200 && id->driver_data != mid->driver_data)
dev_notice(&client->dev,
"Device mismatch: Configured %s, detected %s\n",
id->name, mid->name);
info = kzalloc(sizeof(struct pmbus_driver_info), GFP_KERNEL);
if (!info)
return -ENOMEM;
ret = i2c_smbus_read_block_data(client, UCD9200_PHASE_INFO,
block_buffer);
if (ret < 0) {
dev_err(&client->dev, "Failed to read phase information\n");
goto out;
}
/*
* Calculate number of configured pages (rails) from PHASE_INFO
* register.
* Rails have to be sequential, so we can abort after finding
* the first unconfigured rail.
*/
info->pages = 0;
for (i = 0; i < ret; i++) {
if (!block_buffer[i])
break;
info->pages++;
}
if (!info->pages) {
dev_err(&client->dev, "No rails configured\n");
ret = -ENODEV;
goto out;
}
dev_info(&client->dev, "%d rails configured\n", info->pages);
/*
* Set PHASE registers on all pages to 0xff to ensure that phase
* specific commands will apply to all phases of a given page (rail).
* This only affects the READ_IOUT and READ_TEMPERATURE2 registers.
* READ_IOUT will return the sum of currents of all phases of a rail,
* and READ_TEMPERATURE2 will return the maximum temperature detected
* for the the phases of the rail.
*/
for (i = 0; i < info->pages; i++) {
/*
* Setting PAGE & PHASE fails once in a while for no obvious
* reason, so we need to retry a couple of times.
*/
for (j = 0; j < 3; j++) {
ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, i);
if (ret < 0)
continue;
ret = i2c_smbus_write_byte_data(client, PMBUS_PHASE,
0xff);
if (ret < 0)
continue;
break;
}
if (ret < 0) {
dev_err(&client->dev,
"Failed to initialize PHASE registers\n");
goto out;
}
}
if (info->pages > 1)
i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0);
info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT |
PMBUS_HAVE_IIN | PMBUS_HAVE_PIN |
PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP |
PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;
for (i = 1; i < info->pages; i++)
info->func[i] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
PMBUS_HAVE_POUT |
PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;
/* ucd9240 supports a single fan */
if (mid->driver_data == ucd9240)
info->func[0] |= PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12;
ret = pmbus_do_probe(client, mid, info);
if (ret < 0)
goto out;
return 0;
out:
kfree(info);
return ret;
}
static int ucd9200_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;
}
/* This is the driver that will be inserted */
static struct i2c_driver ucd9200_driver = {
.driver = {
.name = "ucd9200",
},
.probe = ucd9200_probe,
.remove = ucd9200_remove,
.id_table = ucd9200_id,
};
static int __init ucd9200_init(void)
{
return i2c_add_driver(&ucd9200_driver);
}
static void __exit ucd9200_exit(void)
{
i2c_del_driver(&ucd9200_driver);
}
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for TI UCD922x, UCD924x");
MODULE_LICENSE("GPL");
module_init(ucd9200_init);
module_exit(ucd9200_exit);
......@@ -8,17 +8,27 @@
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* For further information, see the Documentation/hwmon/sht15 file.
*/
/**
* struct sht15_platform_data - sht15 connectivity info
* @gpio_data: no. of gpio to which bidirectional data line is connected
* @gpio_sck: no. of gpio to which the data clock is connected.
* @supply_mv: supply voltage in mv. Overridden by regulator if available.
**/
* @gpio_data: no. of gpio to which bidirectional data line is
* connected.
* @gpio_sck: no. of gpio to which the data clock is connected.
* @supply_mv: supply voltage in mv. Overridden by regulator if
* available.
* @checksum: flag to indicate the checksum should be validated.
* @no_otp_reload: flag to indicate no reload from OTP.
* @low_resolution: flag to indicate the temp/humidity resolution to use.
*/
struct sht15_platform_data {
int gpio_data;
int gpio_sck;
int supply_mv;
bool checksum;
bool no_otp_reload;
bool low_resolution;
};
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册