New drivers for NCT6775, NCT6776, NCT6779, and LM95234.

Added support for LTC2974, LTC3883, LM25056, TMP431, TMP432,
 ADT7310, and ADT7320 to existing drivers.
 Various code cleanups and minor improvements.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQIcBAABAgAGBQJRfgHYAAoJEMsfJm/On5mBkJIP/2y4kfcgh+7Ye8nqs0xnPqA0
 +8YR1HYboj8L3HHsWpK0Q3H17yN7bbwESSVeSRKx+UDfPXHYxqKPMdVaVdLU4FwA
 mIdKuOHoTt4dt57XvpXFfCzVeuAeBCoEsGlR5+KeoZV1VyGshSo7nBAZdpUtDghc
 6ZDPROaYY3rCLDsFRuctap3pWZodZSkprt1Kw/Akx8kByv7R/esA9IHRsI/VkWCs
 m2EIaJPfsZANFyGqahauGDA9goj+cqBQqSdFN+hHY5m5Ur7CRfH8z9sDl+r+8L5s
 Ij68kPTdgn9tbCbiomaH1DMmJO/GUeMEc7LFBIAgbTzSbjmgDp7y13zN5rnzoINX
 idFJu7XWL7f6BsipYnIKGpGyd6S7Usfdis+RVxn9LTZ06KK+NYuST0cM+jtlmHwr
 pHNsFsxz5LizPo+ULBSfTb62uRRSfJ7TRaRcZdVS43ha+rsdk/oWf1KUU+U8dpug
 NSxkgZNSFPC98UUJ8VhwV3m09D3O7p60oA8aeP6CJ+ysML6Gq6xg7eipH3n7eft1
 rUbZvVi4vGIFhag0xRTy1IyKXVNYNSAGWzfMpnB6fn5kblmdr0c+wa7rqMDmeThm
 PWNrYasc61zGexPqib7VPGrlt2SiDE2w+/y3kdDPG89smqlieqVS5tJjig8fFPIB
 oHw0Yu7v/6DBjp6a/pjd
 =RxMp
 -----END PGP SIGNATURE-----

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

Pull hwmon update from Guenter Roeck:

 - New drivers for NCT6775, NCT6776, NCT6779, and LM95234.

 - Added support for LTC2974, LTC3883, LM25056, TMP431, TMP432, ADT7310,
   and ADT7320 to existing drivers.

 - Various code cleanups and minor improvements.

* tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (54 commits)
  hwmon: (nct6775) Fix coding style problems
  hwmon: (nct6775) Constify strings
  hwmon: (tmp401) Add support for TMP432
  hwmon: (tmp401) Add support for update_interval attribute
  hwmon: (tmp401) Reset valid flag when resetting temperature history
  hwmon: (tmp401) Simplification and cleanup
  hwmon: (tmp401) Use sysfs_create_group / sysfs_remove_group
  hwmon: (tmp401) Drop unused defines, use BIT for bit masks
  hwmon: (nct6775) Use ARRAY_SIZE for loops where possible
  documentation: hwmon: Fix typo in documentation/hwmon
  hwmon: (nct6775) Enable both AUXTIN and VIN3 on NCT6776
  hwmon: (ad7314) use spi_get_drvdata() and spi_set_drvdata()
  MAINTAINERS: Add myself as maintainer for the NCT6775 driver
  hwmon: (nct6775) Expand scope of supported chips
  hwmon: (gpio-fan) Use is_visible to determine if attributes should be created
  hwmon: (tmp401) Fix device detection for TMP411B and TMP411C
  hwmon: Add driver for LM95234
  hwmon: (tmp401) Add support for TMP431
  hwmon: (pmbus/lm25066) Add support for LM25056
  hwmon: (pmbus/lm25066) Refactor device specific coefficients
  ...
This commit is contained in:
Linus Torvalds 2013-04-29 09:45:48 -07:00
commit 92ddcf4a01
77 changed files with 7860 additions and 1791 deletions

View file

@ -0,0 +1,29 @@
NTC Thermistor hwmon sensors
-------------------------------
Requires node properties:
- "compatible" value : one of
"ntc,ncp15wb473"
"ntc,ncp18wb473"
"ntc,ncp21wb473"
"ntc,ncp03wb473"
"ntc,ncp15wl333"
- "pullup-uv" Pull up voltage in micro volts
- "pullup-ohm" Pull up resistor value in ohms
- "pulldown-ohm" Pull down resistor value in ohms
- "connected-positive" Always ON, If not specified.
Status change is possible.
- "io-channels" Channel node of ADC to be used for
conversion.
Read more about iio bindings at
Documentation/devicetree/bindings/iio/iio-bindings.txt
Example:
ncp15wb473@0 {
compatible = "ntc,ncp15wb473";
pullup-uv = <1800000>;
pullup-ohm = <47000>;
pulldown-ohm = <0>;
io-channels = <&adc 3>;
};

View file

@ -12,29 +12,42 @@ Supported chips:
Addresses scanned: None
Datasheet: Publicly available at the Analog Devices website
http://www.analog.com/static/imported-files/data_sheets/ADT7420.pdf
* Analog Devices ADT7310
Prefix: 'adt7310'
Addresses scanned: None
Datasheet: Publicly available at the Analog Devices website
http://www.analog.com/static/imported-files/data_sheets/ADT7310.pdf
* Analog Devices ADT7320
Prefix: 'adt7320'
Addresses scanned: None
Datasheet: Publicly available at the Analog Devices website
http://www.analog.com/static/imported-files/data_sheets/ADT7320.pdf
Author: Hartmut Knaack <knaack.h@gmx.de>
Description
-----------
The ADT7410 is a temperature sensor with rated temperature range of -55°C to
+150°C. It has a high accuracy of +/-0.5°C and can be operated at a resolution
of 13 bits (0.0625°C) or 16 bits (0.0078°C). The sensor provides an INT pin to
indicate that a minimum or maximum temperature set point has been exceeded, as
well as a critical temperature (CT) pin to indicate that the critical
temperature set point has been exceeded. Both pins can be set up with a common
hysteresis of 0°C - 15°C and a fault queue, ranging from 1 to 4 events. Both
pins can individually set to be active-low or active-high, while the whole
device can either run in comparator mode or interrupt mode. The ADT7410
supports continous temperature sampling, as well as sampling one temperature
value per second or even justget one sample on demand for power saving.
Besides, it can completely power down its ADC, if power management is
required.
The ADT7310/ADT7410 is a temperature sensor with rated temperature range of
-55°C to +150°C. It has a high accuracy of +/-0.5°C and can be operated at a
resolution of 13 bits (0.0625°C) or 16 bits (0.0078°C). The sensor provides an
INT pin to indicate that a minimum or maximum temperature set point has been
exceeded, as well as a critical temperature (CT) pin to indicate that the
critical temperature set point has been exceeded. Both pins can be set up with a
common hysteresis of 0°C - 15°C and a fault queue, ranging from 1 to 4 events.
Both pins can individually set to be active-low or active-high, while the whole
device can either run in comparator mode or interrupt mode. The ADT7410 supports
continuous temperature sampling, as well as sampling one temperature value per
second or even just get one sample on demand for power saving. Besides, it can
completely power down its ADC, if power management is required.
The ADT7420 is register compatible, the only differences being the package,
a slightly narrower operating temperature range (-40°C to +150°C), and a
better accuracy (0.25°C instead of 0.50°C.)
The ADT7320/ADT7420 is register compatible, the only differences being the
package, a slightly narrower operating temperature range (-40°C to +150°C), and
a better accuracy (0.25°C instead of 0.50°C.)
The difference between the ADT7310/ADT7320 and ADT7410/ADT7420 is the control
interface, the ADT7310 and ADT7320 use SPI while the ADT7410 and ADT7420 use
I2C.
Configuration Notes
-------------------

View file

@ -1,7 +1,13 @@
Kernel driver max8688
Kernel driver lm25066
=====================
Supported chips:
* TI LM25056
Prefix: 'lm25056'
Addresses scanned: -
Datasheets:
http://www.ti.com/lit/gpn/lm25056
http://www.ti.com/lit/gpn/lm25056a
* National Semiconductor LM25066
Prefix: 'lm25066'
Addresses scanned: -
@ -25,8 +31,9 @@ Author: Guenter Roeck <linux@roeck-us.net>
Description
-----------
This driver supports hardware montoring for National Semiconductor LM25066,
LM5064, and LM5064 Power Management, Monitoring, Control, and Protection ICs.
This driver supports hardware montoring for National Semiconductor / TI LM25056,
LM25066, LM5064, and LM5064 Power Management, Monitoring, Control, and
Protection ICs.
The driver is a client driver to the core PMBus driver. Please see
Documentation/hwmon/pmbus for details on PMBus client drivers.
@ -60,14 +67,19 @@ in1_max Maximum input voltage.
in1_min_alarm Input voltage low alarm.
in1_max_alarm Input voltage high alarm.
in2_label "vout1"
in2_input Measured output voltage.
in2_average Average measured output voltage.
in2_min Minimum output voltage.
in2_min_alarm Output voltage low alarm.
in2_label "vmon"
in2_input Measured voltage on VAUX pin
in2_min Minimum VAUX voltage (LM25056 only).
in2_max Maximum VAUX voltage (LM25056 only).
in2_min_alarm VAUX voltage low alarm (LM25056 only).
in2_max_alarm VAUX voltage high alarm (LM25056 only).
in3_label "vout2"
in3_input Measured voltage on vaux pin
in3_label "vout1"
Not supported on LM25056.
in3_input Measured output voltage.
in3_average Average measured output voltage.
in3_min Minimum output voltage.
in3_min_alarm Output voltage low alarm.
curr1_label "iin"
curr1_input Measured input current.

View file

@ -0,0 +1,36 @@
Kernel driver lm95234
=====================
Supported chips:
* National Semiconductor / Texas Instruments LM95234
Addresses scanned: I2C 0x18, 0x4d, 0x4e
Datasheet: Publicly available at the Texas Instruments website
http://www.ti.com/product/lm95234
Author: Guenter Roeck <linux@roeck-us.net>
Description
-----------
LM95234 is an 11-bit digital temperature sensor with a 2-wire System Management
Bus (SMBus) interface and TrueTherm technology that can very accurately monitor
the temperature of four remote diodes as well as its own temperature.
The four remote diodes can be external devices such as microprocessors,
graphics processors or diode-connected 2N3904s. The LM95234's TruTherm
beta compensation technology allows sensing of 90 nm or 65 nm process
thermal diodes accurately.
All temperature values are given in millidegrees Celsius. Temperature
is provided within a range of -127 to +255 degrees (+127.875 degrees for
the internal sensor). Resolution depends on temperature input and range.
Each sensor has its own maximum limit, but the hysteresis is common to all
channels. The hysteresis is configurable with the tem1_max_hyst attribute and
affects the hysteresis on all channels. The first two external sensors also
have a critical limit.
The lm95234 driver can change its update interval to a fixed set of values.
It will round up to the next selectable interval. See the datasheet for exact
values. Reading sensor values more often will do no harm, but will return
'old' values.

View file

@ -2,6 +2,10 @@ Kernel driver ltc2978
=====================
Supported chips:
* Linear Technology LTC2974
Prefix: 'ltc2974'
Addresses scanned: -
Datasheet: http://www.linear.com/product/ltc2974
* Linear Technology LTC2978
Prefix: 'ltc2978'
Addresses scanned: -
@ -10,6 +14,10 @@ Supported chips:
Prefix: 'ltc3880'
Addresses scanned: -
Datasheet: http://www.linear.com/product/ltc3880
* Linear Technology LTC3883
Prefix: 'ltc3883'
Addresses scanned: -
Datasheet: http://www.linear.com/product/ltc3883
Author: Guenter Roeck <linux@roeck-us.net>
@ -17,9 +25,9 @@ Author: Guenter Roeck <linux@roeck-us.net>
Description
-----------
The LTC2978 is an octal power supply monitor, supervisor, sequencer and
margin controller. The LTC3880 is a dual, PolyPhase DC/DC synchronous
step-down switching regulator controller.
LTC2974 is a quad digital power supply manager. LTC2978 is an octal power supply
monitor. LTC3880 is a dual output poly-phase step-down DC/DC controller. LTC3883
is a single phase step-down DC/DC controller.
Usage Notes
@ -41,63 +49,90 @@ Sysfs attributes
in1_label "vin"
in1_input Measured input voltage.
in1_min Minimum input voltage.
in1_max Maximum input voltage.
in1_lcrit Critical minimum input voltage.
in1_max Maximum input voltage. LTC2974 and LTC2978 only.
in1_lcrit Critical minimum input voltage. LTC2974 and LTC2978
only.
in1_crit Critical maximum input voltage.
in1_min_alarm Input voltage low alarm.
in1_max_alarm Input voltage high alarm.
in1_lcrit_alarm Input voltage critical low alarm.
in1_max_alarm Input voltage high alarm. LTC2974 and LTC2978 only.
in1_lcrit_alarm Input voltage critical low alarm. LTC2974 and LTC2978
only.
in1_crit_alarm Input voltage critical high alarm.
in1_lowest Lowest input voltage. LTC2978 only.
in1_lowest Lowest input voltage. LTC2974 and LTC2978 only.
in1_highest Highest input voltage.
in1_reset_history Reset history. Writing into this attribute will reset
history for all attributes.
in1_reset_history Reset input voltage history.
in[2-9]_label "vout[1-8]". Channels 3 to 9 on LTC2978 only.
in[2-9]_input Measured output voltage.
in[2-9]_min Minimum output voltage.
in[2-9]_max Maximum output voltage.
in[2-9]_lcrit Critical minimum output voltage.
in[2-9]_crit Critical maximum output voltage.
in[2-9]_min_alarm Output voltage low alarm.
in[2-9]_max_alarm Output voltage high alarm.
in[2-9]_lcrit_alarm Output voltage critical low alarm.
in[2-9]_crit_alarm Output voltage critical high alarm.
in[2-9]_lowest Lowest output voltage. LTC2978 only.
in[2-9]_highest Lowest output voltage.
in[2-9]_reset_history Reset history. Writing into this attribute will reset
history for all attributes.
in[N]_label "vout[1-8]".
LTC2974: N=2-5
LTC2978: N=2-9
LTC3880: N=2-3
LTC3883: N=2
in[N]_input Measured output voltage.
in[N]_min Minimum output voltage.
in[N]_max Maximum output voltage.
in[N]_lcrit Critical minimum output voltage.
in[N]_crit Critical maximum output voltage.
in[N]_min_alarm Output voltage low alarm.
in[N]_max_alarm Output voltage high alarm.
in[N]_lcrit_alarm Output voltage critical low alarm.
in[N]_crit_alarm Output voltage critical high alarm.
in[N]_lowest Lowest output voltage. LTC2974 and LTC2978 only.
in[N]_highest Highest output voltage.
in[N]_reset_history Reset output voltage history.
temp[1-3]_input Measured temperature.
temp[N]_input Measured temperature.
On LTC2974, temp[1-4] report external temperatures,
and temp5 reports the chip temperature.
On LTC2978, only one temperature measurement is
supported and reflects the internal temperature.
supported and reports the chip temperature.
On LTC3880, temp1 and temp2 report external
temperatures, and temp3 reports the internal
temperature.
temp[1-3]_min Mimimum temperature.
temp[1-3]_max Maximum temperature.
temp[1-3]_lcrit Critical low temperature.
temp[1-3]_crit Critical high temperature.
temp[1-3]_min_alarm Chip temperature low alarm.
temp[1-3]_max_alarm Chip temperature high alarm.
temp[1-3]_lcrit_alarm Chip temperature critical low alarm.
temp[1-3]_crit_alarm Chip temperature critical high alarm.
temp[1-3]_lowest Lowest measured temperature. LTC2978 only.
temp[1-3]_highest Highest measured temperature.
temp[1-3]_reset_history Reset history. Writing into this attribute will reset
history for all attributes.
temperatures, and temp3 reports the chip temperature.
On LTC3883, temp1 reports an external temperature,
and temp2 reports the chip temperature.
temp[N]_min Mimimum temperature. LTC2974 and LTC2978 only.
temp[N]_max Maximum temperature.
temp[N]_lcrit Critical low temperature.
temp[N]_crit Critical high temperature.
temp[N]_min_alarm Temperature low alarm. LTC2974 and LTC2978 only.
temp[N]_max_alarm Temperature high alarm.
temp[N]_lcrit_alarm Temperature critical low alarm.
temp[N]_crit_alarm Temperature critical high alarm.
temp[N]_lowest Lowest measured temperature. LTC2974 and LTC2978 only.
Not supported for chip temperature sensor on LTC2974.
temp[N]_highest Highest measured temperature. Not supported for chip
temperature sensor on LTC2974.
temp[N]_reset_history Reset temperature history. Not supported for chip
temperature sensor on LTC2974.
power[1-2]_label "pout[1-2]". LTC3880 only.
power[1-2]_input Measured power.
power1_label "pin". LTC3883 only.
power1_input Measured input power.
curr1_label "iin". LTC3880 only.
power[N]_label "pout[1-4]".
LTC2974: N=1-4
LTC2978: Not supported
LTC3880: N=1-2
LTC3883: N=2
power[N]_input Measured output power.
curr1_label "iin". LTC3880 and LTC3883 only.
curr1_input Measured input current.
curr1_max Maximum input current.
curr1_max_alarm Input current high alarm.
curr1_highest Highest input current. LTC3883 only.
curr1_reset_history Reset input current history. LTC3883 only.
curr[2-3]_label "iout[1-2]". LTC3880 only.
curr[2-3]_input Measured input current.
curr[2-3]_max Maximum input current.
curr[2-3]_crit Critical input current.
curr[2-3]_max_alarm Input current high alarm.
curr[2-3]_crit_alarm Input current critical high alarm.
curr[N]_label "iout[1-4]".
LTC2974: N=1-4
LTC2978: not supported
LTC3880: N=2-3
LTC3883: N=2
curr[N]_input Measured output current.
curr[N]_max Maximum output current.
curr[N]_crit Critical high output current.
curr[N]_lcrit Critical low output current. LTC2974 only.
curr[N]_max_alarm Output current high alarm.
curr[N]_crit_alarm Output current critical high alarm.
curr[N]_lcrit_alarm Output current critical low alarm. LTC2974 only.
curr[N]_lowest Lowest output current. LTC2974 only.
curr[N]_highest Highest output current.
curr[N]_reset_history Reset output current history.

188
Documentation/hwmon/nct6775 Normal file
View file

@ -0,0 +1,188 @@
Note
====
This driver supersedes the NCT6775F and NCT6776F support in the W83627EHF
driver.
Kernel driver NCT6775
=====================
Supported chips:
* Nuvoton NCT5572D/NCT6771F/NCT6772F/NCT6775F/W83677HG-I
Prefix: 'nct6775'
Addresses scanned: ISA address retrieved from Super I/O registers
Datasheet: Available from Nuvoton upon request
* Nuvoton NCT5577D/NCT6776D/NCT6776F
Prefix: 'nct6776'
Addresses scanned: ISA address retrieved from Super I/O registers
Datasheet: Available from Nuvoton upon request
* Nuvoton NCT5532D/NCT6779D
Prefix: 'nct6779'
Addresses scanned: ISA address retrieved from Super I/O registers
Datasheet: Available from Nuvoton upon request
Authors:
Guenter Roeck <linux@roeck-us.net>
Description
-----------
This driver implements support for the Nuvoton NCT6775F, NCT6776F, and NCT6779D
and compatible super I/O chips.
The chips support up to 25 temperature monitoring sources. Up to 6 of those are
direct temperature sensor inputs, the others are special sources such as PECI,
PCH, and SMBUS. Depending on the chip type, 2 to 6 of the temperature sources
can be monitored and compared against minimum, maximum, and critical
temperatures. The driver reports up to 10 of the temperatures to the user.
There are 4 to 5 fan rotation speed sensors, 8 to 15 analog voltage sensors,
one VID, alarms with beep warnings (control unimplemented), and some automatic
fan regulation strategies (plus manual fan control mode).
The temperature sensor sources on all chips are configurable. The configured
source for each of the temperature sensors is provided in tempX_label.
Temperatures are measured in degrees Celsius and measurement resolution is
either 1 degC or 0.5 degC, depending on the temperature source and
configuration. An alarm is triggered when the temperature gets higher than
the high limit; it stays on until the temperature falls below the hysteresis
value. Alarms are only supported for temp1 to temp6, depending on the chip type.
Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
triggered if the rotation speed has dropped below a programmable limit. On
NCT6775F, fan readings can be divided by a programmable divider (1, 2, 4, 8,
16, 32, 64 or 128) to give the readings more range or accuracy; the other chips
do not have a fan speed divider. The driver sets the most suitable fan divisor
itself; specifically, it increases the divider value each time a fan speed
reading returns an invalid value, and it reduces it if the fan speed reading
is lower than optimal. Some fans might not be present because they share pins
with other functions.
Voltage sensors (also known as IN sensors) report their values in millivolts.
An alarm is triggered if the voltage has crossed a programmable minimum
or maximum limit.
The driver supports automatic fan control mode known as Thermal Cruise.
In this mode, the chip attempts to keep the measured temperature in a
predefined temperature range. If the temperature goes out of range, fan
is driven slower/faster to reach the predefined range again.
The mode works for fan1-fan5.
sysfs attributes
----------------
pwm[1-5] - this file stores PWM duty cycle or DC value (fan speed) in range:
0 (lowest speed) to 255 (full)
pwm[1-5]_enable - this file controls mode of fan/temperature control:
* 0 Fan control disabled (fans set to maximum speed)
* 1 Manual mode, write to pwm[0-5] any value 0-255
* 2 "Thermal Cruise" mode
* 3 "Fan Speed Cruise" mode
* 4 "Smart Fan III" mode (NCT6775F only)
* 5 "Smart Fan IV" mode
pwm[1-5]_mode - controls if output is PWM or DC level
* 0 DC output
* 1 PWM output
Common fan control attributes
-----------------------------
pwm[1-5]_temp_sel Temperature source. Value is temperature sensor index.
For example, select '1' for temp1_input.
pwm[1-5]_weight_temp_sel
Secondary temperature source. Value is temperature
sensor index. For example, select '1' for temp1_input.
Set to 0 to disable secondary temperature control.
If secondary temperature functionality is enabled, it is controlled with the
following attributes.
pwm[1-5]_weight_duty_step
Duty step size.
pwm[1-5]_weight_temp_step
Temperature step size. With each step over
temp_step_base, the value of weight_duty_step is added
to the current pwm value.
pwm[1-5]_weight_temp_step_base
Temperature at which secondary temperature control kicks
in.
pwm[1-5]_weight_temp_step_tol
Temperature step tolerance.
Thermal Cruise mode (2)
-----------------------
If the temperature is in the range defined by:
pwm[1-5]_target_temp Target temperature, unit millidegree Celsius
(range 0 - 127000)
pwm[1-5]_temp_tolerance
Target temperature tolerance, unit millidegree Celsius
there are no changes to fan speed. Once the temperature leaves the interval, fan
speed increases (if temperature is higher that desired) or decreases (if
temperature is lower than desired), using the following limits and time
intervals.
pwm[1-5]_start fan pwm start value (range 1 - 255), to start fan
when the temperature is above defined range.
pwm[1-5]_floor lowest fan pwm (range 0 - 255) if temperature is below
the defined range. If set to 0, the fan is expected to
stop if the temperature is below the defined range.
pwm[1-5]_step_up_time milliseconds before fan speed is increased
pwm[1-5]_step_down_time milliseconds before fan speed is decreased
pwm[1-5]_stop_time how many milliseconds must elapse to switch
corresponding fan off (when the temperature was below
defined range).
Speed Cruise mode (3)
---------------------
This modes tries to keep the fan speed constant.
fan[1-5]_target Target fan speed
fan[1-5]_tolerance
Target speed tolerance
Untested; use at your own risk.
Smart Fan IV mode (5)
---------------------
This mode offers multiple slopes to control the fan speed. The slopes can be
controlled by setting the pwm and temperature attributes. When the temperature
rises, the chip will calculate the DC/PWM output based on the current slope.
There are up to seven data points depending on the chip type. Subsequent data
points should be set to higher temperatures and higher pwm values to achieve
higher fan speeds with increasing temperature. The last data point reflects
critical temperature mode, in which the fans should run at full speed.
pwm[1-5]_auto_point[1-7]_pwm
pwm value to be set if temperature reaches matching
temperature range.
pwm[1-5]_auto_point[1-7]_temp
Temperature over which the matching pwm is enabled.
pwm[1-5]_temp_tolerance
Temperature tolerance, unit millidegree Celsius
pwm[1-5]_crit_temp_tolerance
Temperature tolerance for critical temperature,
unit millidegree Celsius
pwm[1-5]_step_up_time milliseconds before fan speed is increased
pwm[1-5]_step_down_time milliseconds before fan speed is decreased
Usage Notes
-----------
On various ASUS boards with NCT6776F, it appears that CPUTIN is not really
connected to anything and floats, or that it is connected to some non-standard
temperature measurement device. As a result, the temperature reported on CPUTIN
will not reflect a usable value. It often reports unreasonably high
temperatures, and in some cases the reported temperature declines if the actual
temperature increases (similar to the raw PECI temperature value - see PECI
specification for details). CPUTIN should therefore be be ignored on ASUS
boards. The CPU temperature on ASUS boards is reported from PECI 0.

View file

@ -40,7 +40,7 @@ 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.
measurement and decrease power consumption, while losing on precision.
Some options may be set directly in the sht15_platform_data structure
or via sysfs attributes.

View file

@ -8,8 +8,16 @@ Supported chips:
Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp401.html
* Texas Instruments TMP411
Prefix: 'tmp411'
Addresses scanned: I2C 0x4c
Addresses scanned: I2C 0x4c, 0x4d, 0x4e
Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp411.html
* Texas Instruments TMP431
Prefix: 'tmp431'
Addresses scanned: I2C 0x4c, 0x4d
Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp431.html
* Texas Instruments TMP432
Prefix: 'tmp432'
Addresses scanned: I2C 0x4c, 0x4d
Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp432.html
Authors:
Hans de Goede <hdegoede@redhat.com>
@ -18,19 +26,19 @@ Authors:
Description
-----------
This driver implements support for Texas Instruments TMP401 and
TMP411 chips. These chips implements one remote and one local
temperature sensor. Temperature is measured in degrees
This driver implements support for Texas Instruments TMP401, TMP411,
TMP431, and TMP432 chips. These chips implement one or two remote and
one local temperature sensors. Temperature is measured in degrees
Celsius. Resolution of the remote sensor is 0.0625 degree. Local
sensor resolution can be set to 0.5, 0.25, 0.125 or 0.0625 degree (not
supported by the driver so far, so using the default resolution of 0.5
degree).
The driver provides the common sysfs-interface for temperatures (see
/Documentation/hwmon/sysfs-interface under Temperatures).
Documentation/hwmon/sysfs-interface under Temperatures).
The TMP411 chip is compatible with TMP401. It provides some additional
features.
The TMP411 and TMP431 chips are compatible with TMP401. TMP411 provides
some additional features.
* Minimum and Maximum temperature measured since power-on, chip-reset
@ -40,3 +48,6 @@ features.
Exported via sysfs attribute temp_reset_history. Writing 1 to this
file triggers a reset.
TMP432 is compatible with TMP401 and TMP431. It supports two external
temperature sensors.

View file

@ -125,7 +125,7 @@ in2_label "vmon"
in2_input Measured voltage on VMON (ZL2004) or VDRV (ZL9101M,
ZL9117M) pin. Reported voltage is 16x the voltage on the
pin (adjusted internally by the chip).
in2_lcrit Critical minumum VMON/VDRV Voltage.
in2_lcrit Critical minimum VMON/VDRV Voltage.
in2_crit Critical maximum VMON/VDRV voltage.
in2_lcrit_alarm VMON/VDRV voltage critical low alarm.
in2_crit_alarm VMON/VDRV voltage critical high alarm.

View file

@ -5412,6 +5412,13 @@ L: linux-scsi@vger.kernel.org
S: Maintained
F: drivers/scsi/NCR_D700.*
NCT6775 HARDWARE MONITOR DRIVER
M: Guenter Roeck <linux@roeck-us.net>
L: lm-sensors@lm-sensors.org
S: Maintained
F: Documentation/hwmon/nct6775
F: drivers/hwmon/nct6775.c
NETEFFECT IWARP RNIC DRIVER (IW_NES)
M: Faisal Latif <faisal.latif@intel.com>
L: linux-rdma@vger.kernel.org

View file

@ -179,9 +179,29 @@ config SENSORS_ADM9240
This driver can also be built as a module. If so, the module
will be called adm9240.
config SENSORS_ADT7X10
tristate
help
This module contains common code shared by the ADT7310/ADT7320 and
ADT7410/ADT7420 temperature monitoring chip drivers.
If build as a module, the module will be called adt7x10.
config SENSORS_ADT7310
tristate "Analog Devices ADT7310/ADT7320"
depends on SPI_MASTER
select SENSORS_ADT7X10
help
If you say yes here you get support for the Analog Devices
ADT7310 and ADT7320 temperature monitoring chips.
This driver can also be built as a module. If so, the module
will be called adt7310.
config SENSORS_ADT7410
tristate "Analog Devices ADT7410/ADT7420"
depends on I2C
select SENSORS_ADT7X10
help
If you say yes here you get support for the Analog Devices
ADT7410 and ADT7420 temperature monitoring chips.
@ -751,6 +771,16 @@ config SENSORS_LTC4261
This driver can also be built as a module. If so, the module will
be called ltc4261.
config SENSORS_LM95234
tristate "National Semiconductor LM95234"
depends on I2C
help
If you say yes here you get support for the LM95234 temperature
sensor.
This driver can also be built as a module. If so, the module
will be called lm95234.
config SENSORS_LM95241
tristate "National Semiconductor LM95241 and compatibles"
depends on I2C
@ -877,8 +907,22 @@ config SENSORS_MCP3021
This driver can also be built as a module. If so, the module
will be called mcp3021.
config SENSORS_NCT6775
tristate "Nuvoton NCT6775F and compatibles"
depends on !PPC
select HWMON_VID
help
If you say yes here you get support for the hardware monitoring
functionality of the Nuvoton NCT6775F, NCT6776F, NCT6779D
and compatible Super-I/O chips. This driver replaces the
w83627ehf driver for NCT6775F and NCT6776F.
This driver can also be built as a module. If so, the module
will be called nct6775.
config SENSORS_NTC_THERMISTOR
tristate "NTC thermistor support"
depends on (!OF && !IIO) || (OF && IIO)
help
This driver supports NTC thermistors sensor reading and its
interpretation. The driver can also monitor the temperature and
@ -1204,8 +1248,8 @@ config SENSORS_TMP401
tristate "Texas Instruments TMP401 and compatibles"
depends on I2C
help
If you say yes here you get support for Texas Instruments TMP401 and
TMP411 temperature sensor chips.
If you say yes here you get support for Texas Instruments TMP401,
TMP411, TMP431, and TMP432 temperature sensor chips.
This driver can also be built as a module. If so, the module
will be called tmp401.

View file

@ -34,6 +34,8 @@ obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o
obj-$(CONFIG_SENSORS_ADS1015) += ads1015.o
obj-$(CONFIG_SENSORS_ADS7828) += ads7828.o
obj-$(CONFIG_SENSORS_ADS7871) += ads7871.o
obj-$(CONFIG_SENSORS_ADT7X10) += adt7x10.o
obj-$(CONFIG_SENSORS_ADT7310) += adt7310.o
obj-$(CONFIG_SENSORS_ADT7410) += adt7410.o
obj-$(CONFIG_SENSORS_ADT7411) += adt7411.o
obj-$(CONFIG_SENSORS_ADT7462) += adt7462.o
@ -86,6 +88,7 @@ obj-$(CONFIG_SENSORS_LM87) += lm87.o
obj-$(CONFIG_SENSORS_LM90) += lm90.o
obj-$(CONFIG_SENSORS_LM92) += lm92.o
obj-$(CONFIG_SENSORS_LM93) += lm93.o
obj-$(CONFIG_SENSORS_LM95234) += lm95234.o
obj-$(CONFIG_SENSORS_LM95241) += lm95241.o
obj-$(CONFIG_SENSORS_LM95245) += lm95245.o
obj-$(CONFIG_SENSORS_LTC4151) += ltc4151.o
@ -103,6 +106,7 @@ obj-$(CONFIG_SENSORS_MAX6650) += max6650.o
obj-$(CONFIG_SENSORS_MAX6697) += max6697.o
obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
obj-$(CONFIG_SENSORS_MCP3021) += mcp3021.o
obj-$(CONFIG_SENSORS_NCT6775) += nct6775.o
obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o
obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
obj-$(CONFIG_SENSORS_PC87427) += pc87427.o

View file

@ -96,9 +96,12 @@
#define ABIT_UGURU_MAX_TIMEOUTS 2
/* utility macros */
#define ABIT_UGURU_NAME "abituguru"
#define ABIT_UGURU_DEBUG(level, format, arg...) \
if (level <= verbose) \
printk(KERN_DEBUG ABIT_UGURU_NAME ": " format , ## arg)
#define ABIT_UGURU_DEBUG(level, format, arg...) \
do { \
if (level <= verbose) \
pr_debug(format , ## arg); \
} while (0)
/* Macros to help calculate the sysfs_names array length */
/*
* sum of strlen of: in??_input\0, in??_{min,max}\0, in??_{min,max}_alarm\0,
@ -1533,7 +1536,7 @@ static int abituguru_resume(struct device *dev)
}
static SIMPLE_DEV_PM_OPS(abituguru_pm, abituguru_suspend, abituguru_resume);
#define ABIT_UGURU_PM &abituguru_pm
#define ABIT_UGURU_PM (&abituguru_pm)
#else
#define ABIT_UGURU_PM NULL
#endif /* CONFIG_PM */

View file

@ -76,9 +76,11 @@
#define ABIT_UGURU3_SYNCHRONIZE_TIMEOUT 5
/* utility macros */
#define ABIT_UGURU3_NAME "abituguru3"
#define ABIT_UGURU3_DEBUG(format, arg...) \
if (verbose) \
printk(KERN_DEBUG ABIT_UGURU3_NAME ": " format , ## arg)
#define ABIT_UGURU3_DEBUG(format, arg...) \
do { \
if (verbose) \
pr_debug(format , ## arg); \
} while (0)
/* Macros to help calculate the sysfs_names array length */
#define ABIT_UGURU3_MAX_NO_SENSORS 26
@ -1159,7 +1161,7 @@ static int abituguru3_resume(struct device *dev)
}
static SIMPLE_DEV_PM_OPS(abituguru3_pm, abituguru3_suspend, abituguru3_resume);
#define ABIT_UGURU3_PM &abituguru3_pm
#define ABIT_UGURU3_PM (&abituguru3_pm)
#else
#define ABIT_UGURU3_PM NULL
#endif /* CONFIG_PM */

View file

@ -116,7 +116,7 @@ static int ad7314_probe(struct spi_device *spi_dev)
if (chip == NULL)
return -ENOMEM;
dev_set_drvdata(&spi_dev->dev, chip);
spi_set_drvdata(spi_dev, chip);
ret = sysfs_create_group(&spi_dev->dev.kobj, &ad7314_group);
if (ret < 0)
@ -137,7 +137,7 @@ error_remove_group:
static int ad7314_remove(struct spi_device *spi_dev)
{
struct ad7314_data *chip = dev_get_drvdata(&spi_dev->dev);
struct ad7314_data *chip = spi_get_drvdata(spi_dev);
hwmon_device_unregister(chip->hwmon_dev);
sysfs_remove_group(&spi_dev->dev.kobj, &ad7314_group);
@ -166,6 +166,5 @@ static struct spi_driver ad7314_driver = {
module_spi_driver(ad7314_driver);
MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD7314, ADT7301 and ADT7302 digital"
" temperature sensor driver");
MODULE_DESCRIPTION("Analog Devices AD7314, ADT7301 and ADT7302 digital temperature sensor driver");
MODULE_LICENSE("GPL v2");

View file

@ -312,8 +312,7 @@ static int adm1021_detect(struct i2c_client *client,
int conv_rate, status, config, man_id, dev_id;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
pr_debug("adm1021: detect failed, "
"smbus byte data not supported!\n");
pr_debug("detect failed, smbus byte data not supported!\n");
return -ENODEV;
}
@ -324,7 +323,7 @@ static int adm1021_detect(struct i2c_client *client,
/* Check unused bits */
if ((status & 0x03) || (config & 0x3F) || (conv_rate & 0xF8)) {
pr_debug("adm1021: detect failed, chip not detected!\n");
pr_debug("detect failed, chip not detected!\n");
return -ENODEV;
}
@ -353,7 +352,7 @@ static int adm1021_detect(struct i2c_client *client,
else
type_name = "max1617";
pr_debug("adm1021: Detected chip %s at adapter %d, address 0x%02x.\n",
pr_debug("Detected chip %s at adapter %d, address 0x%02x.\n",
type_name, i2c_adapter_id(adapter), client->addr);
strlcpy(info->type, type_name, I2C_NAME_SIZE);
@ -368,10 +367,8 @@ static int adm1021_probe(struct i2c_client *client,
data = devm_kzalloc(&client->dev, sizeof(struct adm1021_data),
GFP_KERNEL);
if (!data) {
pr_debug("adm1021: detect failed, devm_kzalloc failed!\n");
if (!data)
return -ENOMEM;
}
i2c_set_clientdata(client, data);
data->type = id->driver_data;

View file

@ -49,14 +49,14 @@ static int gpio_fan[8] = { -1, -1, -1, -1, -1, -1, -1, -1 };
module_param_array(gpio_input, int, NULL, 0);
MODULE_PARM_DESC(gpio_input, "List of GPIO pins (0-16) to program as inputs");
module_param_array(gpio_output, int, NULL, 0);
MODULE_PARM_DESC(gpio_output, "List of GPIO pins (0-16) to program as "
"outputs");
MODULE_PARM_DESC(gpio_output,
"List of GPIO pins (0-16) to program as outputs");
module_param_array(gpio_inverted, int, NULL, 0);
MODULE_PARM_DESC(gpio_inverted, "List of GPIO pins (0-16) to program as "
"inverted");
MODULE_PARM_DESC(gpio_inverted,
"List of GPIO pins (0-16) to program as inverted");
module_param_array(gpio_normal, int, NULL, 0);
MODULE_PARM_DESC(gpio_normal, "List of GPIO pins (0-16) to program as "
"normal/non-inverted");
MODULE_PARM_DESC(gpio_normal,
"List of GPIO pins (0-16) to program as normal/non-inverted");
module_param_array(gpio_fan, int, NULL, 0);
MODULE_PARM_DESC(gpio_fan, "List of GPIO pins (0-7) to program as fan tachs");
@ -372,31 +372,31 @@ static void adm1026_init_client(struct i2c_client *client)
dev_dbg(&client->dev, "ADM1026_REG_CONFIG1 is: 0x%02x\n",
data->config1);
if ((data->config1 & CFG1_MONITOR) == 0) {
dev_dbg(&client->dev, "Monitoring not currently "
"enabled.\n");
dev_dbg(&client->dev,
"Monitoring not currently enabled.\n");
}
if (data->config1 & CFG1_INT_ENABLE) {
dev_dbg(&client->dev, "SMBALERT interrupts are "
"enabled.\n");
dev_dbg(&client->dev,
"SMBALERT interrupts are enabled.\n");
}
if (data->config1 & CFG1_AIN8_9) {
dev_dbg(&client->dev, "in8 and in9 enabled. "
"temp3 disabled.\n");
dev_dbg(&client->dev,
"in8 and in9 enabled. temp3 disabled.\n");
} else {
dev_dbg(&client->dev, "temp3 enabled. in8 and "
"in9 disabled.\n");
dev_dbg(&client->dev,
"temp3 enabled. in8 and in9 disabled.\n");
}
if (data->config1 & CFG1_THERM_HOT) {
dev_dbg(&client->dev, "Automatic THERM, PWM, "
"and temp limits enabled.\n");
dev_dbg(&client->dev,
"Automatic THERM, PWM, and temp limits enabled.\n");
}
if (data->config3 & CFG3_GPIO16_ENABLE) {
dev_dbg(&client->dev, "GPIO16 enabled. THERM "
"pin disabled.\n");
dev_dbg(&client->dev,
"GPIO16 enabled. THERM pin disabled.\n");
} else {
dev_dbg(&client->dev, "THERM pin enabled. "
"GPIO16 disabled.\n");
dev_dbg(&client->dev,
"THERM pin enabled. GPIO16 disabled.\n");
}
if (data->config3 & CFG3_VREF_250)
dev_dbg(&client->dev, "Vref is 2.50 Volts.\n");
@ -1798,8 +1798,8 @@ static int adm1026_detect(struct i2c_client *client,
company = adm1026_read_value(client, ADM1026_REG_COMPANY);
verstep = adm1026_read_value(client, ADM1026_REG_VERSTEP);
dev_dbg(&adapter->dev, "Detecting device at %d,0x%02x with"
" COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
dev_dbg(&adapter->dev,
"Detecting device at %d,0x%02x with COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
i2c_adapter_id(client->adapter), client->addr,
company, verstep);
@ -1811,11 +1811,12 @@ static int adm1026_detect(struct i2c_client *client,
/* Analog Devices ADM1026 */
} else if (company == ADM1026_COMPANY_ANALOG_DEV
&& (verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) {
dev_err(&adapter->dev, "Unrecognized stepping "
"0x%02x. Defaulting to ADM1026.\n", verstep);
dev_err(&adapter->dev,
"Unrecognized stepping 0x%02x. Defaulting to ADM1026.\n",
verstep);
} else if ((verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) {
dev_err(&adapter->dev, "Found version/stepping "
"0x%02x. Assuming generic ADM1026.\n",
dev_err(&adapter->dev,
"Found version/stepping 0x%02x. Assuming generic ADM1026.\n",
verstep);
} else {
dev_dbg(&adapter->dev, "Autodetection failed\n");

View file

@ -224,8 +224,9 @@ static ssize_t set_fan_div(struct device *dev,
break;
default:
mutex_unlock(&data->update_lock);
dev_err(&client->dev, "fan_div value %ld not "
"supported. Choose one of 1, 2 or 4!\n", val);
dev_err(&client->dev,
"fan_div value %ld not supported. Choose one of 1, 2 or 4!\n",
val);
return -EINVAL;
}
/* Update the value */
@ -326,8 +327,8 @@ static int adm1029_detect(struct i2c_client *client,
* There are no "official" CHIP ID, so actually
* we use Major/Minor revision for that
*/
pr_info("adm1029: Unknown major revision %x, "
"please let us know\n", chip_id);
pr_info("Unknown major revision %x, please let us know\n",
chip_id);
return -ENODEV;
}

View file

@ -351,8 +351,9 @@ static void adm9240_write_fan_div(struct i2c_client *client, int nr,
reg &= ~(3 << shift);
reg |= (fan_div << shift);
i2c_smbus_write_byte_data(client, ADM9240_REG_VID_FAN_DIV, reg);
dev_dbg(&client->dev, "fan%d clock divider changed from %u "
"to %u\n", nr + 1, 1 << old, 1 << fan_div);
dev_dbg(&client->dev,
"fan%d clock divider changed from %u to %u\n",
nr + 1, 1 << old, 1 << fan_div);
}
/*
@ -699,8 +700,8 @@ static void adm9240_init_client(struct i2c_client *client)
/* start measurement cycle */
i2c_smbus_write_byte_data(client, ADM9240_REG_CONFIG, 1);
dev_info(&client->dev, "cold start: config was 0x%02x "
"mode %u\n", conf, mode);
dev_info(&client->dev,
"cold start: config was 0x%02x mode %u\n", conf, mode);
}
}

View file

@ -40,25 +40,25 @@
* the instruction byte
*/
/*Instruction Bit masks*/
#define INST_MODE_bm (1<<7)
#define INST_READ_bm (1<<6)
#define INST_16BIT_bm (1<<5)
#define INST_MODE_BM (1 << 7)
#define INST_READ_BM (1 << 6)
#define INST_16BIT_BM (1 << 5)
/*From figure 18 in the datasheet*/
/*bit masks for Rev/Oscillator Control Register*/
#define MUX_CNV_bv 7
#define MUX_CNV_bm (1<<MUX_CNV_bv)
#define MUX_M3_bm (1<<3) /*M3 selects single ended*/
#define MUX_G_bv 4 /*allows for reg = (gain << MUX_G_bv) | ...*/
#define MUX_CNV_BV 7
#define MUX_CNV_BM (1 << MUX_CNV_BV)
#define MUX_M3_BM (1 << 3) /*M3 selects single ended*/
#define MUX_G_BV 4 /*allows for reg = (gain << MUX_G_BV) | ...*/
/*From figure 18 in the datasheet*/
/*bit masks for Rev/Oscillator Control Register*/
#define OSC_OSCR_bm (1<<5)
#define OSC_OSCE_bm (1<<4)
#define OSC_REFE_bm (1<<3)
#define OSC_BUFE_bm (1<<2)
#define OSC_R2V_bm (1<<1)
#define OSC_RBG_bm (1<<0)
#define OSC_OSCR_BM (1 << 5)
#define OSC_OSCE_BM (1 << 4)
#define OSC_REFE_BM (1 << 3)
#define OSC_BUFE_BM (1 << 2)
#define OSC_R2V_BM (1 << 1)
#define OSC_RBG_BM (1 << 0)
#include <linux/module.h>
#include <linux/init.h>
@ -79,7 +79,7 @@ struct ads7871_data {
static int ads7871_read_reg8(struct spi_device *spi, int reg)
{
int ret;
reg = reg | INST_READ_bm;
reg = reg | INST_READ_BM;
ret = spi_w8r8(spi, reg);
return ret;
}
@ -87,7 +87,7 @@ static int ads7871_read_reg8(struct spi_device *spi, int reg)
static int ads7871_read_reg16(struct spi_device *spi, int reg)
{
int ret;
reg = reg | INST_READ_bm | INST_16BIT_bm;
reg = reg | INST_READ_BM | INST_16BIT_BM;
ret = spi_w8r16(spi, reg);
return ret;
}
@ -111,13 +111,13 @@ static ssize_t show_voltage(struct device *dev,
* TODO: add support for conversions
* other than single ended with a gain of 1
*/
/*MUX_M3_bm forces single ended*/
/*MUX_M3_BM forces single ended*/
/*This is also where the gain of the PGA would be set*/
ads7871_write_reg8(spi, REG_GAIN_MUX,
(MUX_CNV_bm | MUX_M3_bm | channel));
(MUX_CNV_BM | MUX_M3_BM | channel));
ret = ads7871_read_reg8(spi, REG_GAIN_MUX);
mux_cnv = ((ret & MUX_CNV_bm)>>MUX_CNV_bv);
mux_cnv = ((ret & MUX_CNV_BM) >> MUX_CNV_BV);
/*
* on 400MHz arm9 platform the conversion
* is already done when we do this test
@ -125,14 +125,14 @@ static ssize_t show_voltage(struct device *dev,
while ((i < 2) && mux_cnv) {
i++;
ret = ads7871_read_reg8(spi, REG_GAIN_MUX);
mux_cnv = ((ret & MUX_CNV_bm)>>MUX_CNV_bv);
mux_cnv = ((ret & MUX_CNV_BM) >> MUX_CNV_BV);
msleep_interruptible(1);
}
if (mux_cnv == 0) {
val = ads7871_read_reg16(spi, REG_LS_BYTE);
/*result in volts*10000 = (val/8192)*2.5*10000*/
val = ((val>>2) * 25000) / 8192;
val = ((val >> 2) * 25000) / 8192;
return sprintf(buf, "%d\n", val);
} else {
return -1;
@ -189,7 +189,7 @@ static int ads7871_probe(struct spi_device *spi)
ads7871_write_reg8(spi, REG_SER_CONTROL, 0);
ads7871_write_reg8(spi, REG_AD_CONTROL, 0);
val = (OSC_OSCR_bm | OSC_OSCE_bm | OSC_REFE_bm | OSC_BUFE_bm);
val = (OSC_OSCR_BM | OSC_OSCE_BM | OSC_REFE_BM | OSC_BUFE_BM);
ads7871_write_reg8(spi, REG_OSC_CONTROL, val);
ret = ads7871_read_reg8(spi, REG_OSC_CONTROL);

123
drivers/hwmon/adt7310.c Normal file
View file

@ -0,0 +1,123 @@
/*
* ADT7310/ADT7310 digital temperature sensor driver
*
* Copyright 2012-2013 Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
*
* Licensed under the GPL-2 or later.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/spi/spi.h>
#include <asm/unaligned.h>
#include "adt7x10.h"
#define ADT7310_STATUS 0
#define ADT7310_CONFIG 1
#define ADT7310_TEMPERATURE 2
#define ADT7310_ID 3
#define ADT7310_T_CRIT 4
#define ADT7310_T_HYST 5
#define ADT7310_T_ALARM_HIGH 6
#define ADT7310_T_ALARM_LOW 7
static const u8 adt7310_reg_table[] = {
[ADT7X10_TEMPERATURE] = ADT7310_TEMPERATURE,
[ADT7X10_STATUS] = ADT7310_STATUS,
[ADT7X10_CONFIG] = ADT7310_CONFIG,
[ADT7X10_T_ALARM_HIGH] = ADT7310_T_ALARM_HIGH,
[ADT7X10_T_ALARM_LOW] = ADT7310_T_ALARM_LOW,
[ADT7X10_T_CRIT] = ADT7310_T_CRIT,
[ADT7X10_T_HYST] = ADT7310_T_HYST,
[ADT7X10_ID] = ADT7310_ID,
};
#define ADT7310_CMD_REG_OFFSET 3
#define ADT7310_CMD_READ 0x40
#define AD7310_COMMAND(reg) (adt7310_reg_table[(reg)] << ADT7310_CMD_REG_OFFSET)
static int adt7310_spi_read_word(struct device *dev, u8 reg)
{
struct spi_device *spi = to_spi_device(dev);
int ret;
ret = spi_w8r16(spi, AD7310_COMMAND(reg) | ADT7310_CMD_READ);
if (ret < 0)
return ret;
return be16_to_cpu((__force __be16)ret);
}
static int adt7310_spi_write_word(struct device *dev, u8 reg, u16 data)
{
struct spi_device *spi = to_spi_device(dev);
u8 buf[3];
buf[0] = AD7310_COMMAND(reg);
put_unaligned_be16(data, &buf[1]);
return spi_write(spi, buf, sizeof(buf));
}
static int adt7310_spi_read_byte(struct device *dev, u8 reg)
{
struct spi_device *spi = to_spi_device(dev);
return spi_w8r8(spi, AD7310_COMMAND(reg) | ADT7310_CMD_READ);
}
static int adt7310_spi_write_byte(struct device *dev, u8 reg,
u8 data)
{
struct spi_device *spi = to_spi_device(dev);
u8 buf[2];
buf[0] = AD7310_COMMAND(reg);
buf[1] = data;
return spi_write(spi, buf, sizeof(buf));
}
static const struct adt7x10_ops adt7310_spi_ops = {
.read_word = adt7310_spi_read_word,
.write_word = adt7310_spi_write_word,
.read_byte = adt7310_spi_read_byte,
.write_byte = adt7310_spi_write_byte,
};
static int adt7310_spi_probe(struct spi_device *spi)
{
return adt7x10_probe(&spi->dev, spi_get_device_id(spi)->name, spi->irq,
&adt7310_spi_ops);
}
static int adt7310_spi_remove(struct spi_device *spi)
{
return adt7x10_remove(&spi->dev, spi->irq);
}
static const struct spi_device_id adt7310_id[] = {
{ "adt7310", 0 },
{ "adt7320", 0 },
{}
};
MODULE_DEVICE_TABLE(spi, adt7310_id);
static struct spi_driver adt7310_driver = {
.driver = {
.name = "adt7310",
.owner = THIS_MODULE,
.pm = ADT7X10_DEV_PM_OPS,
},
.probe = adt7310_spi_probe,
.remove = adt7310_spi_remove,
.id_table = adt7310_id,
};
module_spi_driver(adt7310_driver);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("ADT7310/ADT7320 driver");
MODULE_LICENSE("GPL");

View file

@ -1,460 +1,80 @@
/*
* adt7410.c - Part of lm_sensors, Linux kernel modules for hardware
* monitoring
* This driver handles the ADT7410 and compatible digital temperature sensors.
* Hartmut Knaack <knaack.h@gmx.de> 2012-07-22
* based on lm75.c by Frodo Looijaard <frodol@dds.nl>
* and adt7410.c from iio-staging by Sonic Zhang <sonic.zhang@analog.com>
* ADT7410/ADT7420 digital temperature sensor driver
*
* 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.
* Copyright 2012-2013 Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
*
* 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.
* Licensed under the GPL-2 or later.
*/
#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/delay.h>
/*
* ADT7410 registers definition
*/
#include "adt7x10.h"
#define ADT7410_TEMPERATURE 0
#define ADT7410_STATUS 2
#define ADT7410_CONFIG 3
#define ADT7410_T_ALARM_HIGH 4
#define ADT7410_T_ALARM_LOW 6
#define ADT7410_T_CRIT 8
#define ADT7410_T_HYST 0xA
static int adt7410_i2c_read_word(struct device *dev, u8 reg)
{
return i2c_smbus_read_word_swapped(to_i2c_client(dev), reg);
}
/*
* ADT7410 status
*/
#define ADT7410_STAT_T_LOW (1 << 4)
#define ADT7410_STAT_T_HIGH (1 << 5)
#define ADT7410_STAT_T_CRIT (1 << 6)
#define ADT7410_STAT_NOT_RDY (1 << 7)
static int adt7410_i2c_write_word(struct device *dev, u8 reg, u16 data)
{
return i2c_smbus_write_word_swapped(to_i2c_client(dev), reg, data);
}
/*
* ADT7410 config
*/
#define ADT7410_FAULT_QUEUE_MASK (1 << 0 | 1 << 1)
#define ADT7410_CT_POLARITY (1 << 2)
#define ADT7410_INT_POLARITY (1 << 3)
#define ADT7410_EVENT_MODE (1 << 4)
#define ADT7410_MODE_MASK (1 << 5 | 1 << 6)
#define ADT7410_FULL (0 << 5 | 0 << 6)
#define ADT7410_PD (1 << 5 | 1 << 6)
#define ADT7410_RESOLUTION (1 << 7)
static int adt7410_i2c_read_byte(struct device *dev, u8 reg)
{
return i2c_smbus_read_byte_data(to_i2c_client(dev), reg);
}
/*
* ADT7410 masks
*/
#define ADT7410_T13_VALUE_MASK 0xFFF8
#define ADT7410_T_HYST_MASK 0xF
static int adt7410_i2c_write_byte(struct device *dev, u8 reg, u8 data)
{
return i2c_smbus_write_byte_data(to_i2c_client(dev), reg, data);
}
/* straight from the datasheet */
#define ADT7410_TEMP_MIN (-55000)
#define ADT7410_TEMP_MAX 150000
enum adt7410_type { /* keep sorted in alphabetical order */
adt7410,
static const struct adt7x10_ops adt7410_i2c_ops = {
.read_word = adt7410_i2c_read_word,
.write_word = adt7410_i2c_write_word,
.read_byte = adt7410_i2c_read_byte,
.write_byte = adt7410_i2c_write_byte,
};
static const u8 ADT7410_REG_TEMP[4] = {
ADT7410_TEMPERATURE, /* input */
ADT7410_T_ALARM_HIGH, /* high */
ADT7410_T_ALARM_LOW, /* low */
ADT7410_T_CRIT, /* critical */
};
/* Each client has this additional data */
struct adt7410_data {
struct device *hwmon_dev;
struct mutex update_lock;
u8 config;
u8 oldconfig;
bool valid; /* true if registers valid */
unsigned long last_updated; /* In jiffies */
s16 temp[4]; /* Register values,
0 = input
1 = high
2 = low
3 = critical */
u8 hyst; /* hysteresis offset */
};
/*
* adt7410 register access by I2C
*/
static int adt7410_temp_ready(struct i2c_client *client)
static int adt7410_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int i, status;
for (i = 0; i < 6; i++) {
status = i2c_smbus_read_byte_data(client, ADT7410_STATUS);
if (status < 0)
return status;
if (!(status & ADT7410_STAT_NOT_RDY))
return 0;
msleep(60);
}
return -ETIMEDOUT;
}
static struct adt7410_data *adt7410_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct adt7410_data *data = i2c_get_clientdata(client);
struct adt7410_data *ret = data;
mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|| !data->valid) {
int i, status;
dev_dbg(&client->dev, "Starting update\n");
status = adt7410_temp_ready(client); /* check for new value */
if (unlikely(status)) {
ret = ERR_PTR(status);
goto abort;
}
for (i = 0; i < ARRAY_SIZE(data->temp); i++) {
status = i2c_smbus_read_word_swapped(client,
ADT7410_REG_TEMP[i]);
if (unlikely(status < 0)) {
dev_dbg(dev,
"Failed to read value: reg %d, error %d\n",
ADT7410_REG_TEMP[i], status);
ret = ERR_PTR(status);
goto abort;
}
data->temp[i] = status;
}
status = i2c_smbus_read_byte_data(client, ADT7410_T_HYST);
if (unlikely(status < 0)) {
dev_dbg(dev,
"Failed to read value: reg %d, error %d\n",
ADT7410_T_HYST, status);
ret = ERR_PTR(status);
goto abort;
}
data->hyst = status;
data->last_updated = jiffies;
data->valid = true;
}
abort:
mutex_unlock(&data->update_lock);
return ret;
}
static s16 ADT7410_TEMP_TO_REG(long temp)
{
return DIV_ROUND_CLOSEST(clamp_val(temp, ADT7410_TEMP_MIN,
ADT7410_TEMP_MAX) * 128, 1000);
}
static int ADT7410_REG_TO_TEMP(struct adt7410_data *data, s16 reg)
{
/* in 13 bit mode, bits 0-2 are status flags - mask them out */
if (!(data->config & ADT7410_RESOLUTION))
reg &= ADT7410_T13_VALUE_MASK;
/*
* temperature is stored in twos complement format, in steps of
* 1/128°C
*/
return DIV_ROUND_CLOSEST(reg * 1000, 128);
}
/*-----------------------------------------------------------------------*/
/* sysfs attributes for hwmon */
static ssize_t adt7410_show_temp(struct device *dev,
struct device_attribute *da, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct adt7410_data *data = adt7410_update_device(dev);
if (IS_ERR(data))
return PTR_ERR(data);
return sprintf(buf, "%d\n", ADT7410_REG_TO_TEMP(data,
data->temp[attr->index]));
}
static ssize_t adt7410_set_temp(struct device *dev,
struct device_attribute *da,
const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct i2c_client *client = to_i2c_client(dev);
struct adt7410_data *data = i2c_get_clientdata(client);
int nr = attr->index;
long temp;
int ret;
ret = kstrtol(buf, 10, &temp);
if (ret)
return ret;
mutex_lock(&data->update_lock);
data->temp[nr] = ADT7410_TEMP_TO_REG(temp);
ret = i2c_smbus_write_word_swapped(client, ADT7410_REG_TEMP[nr],
data->temp[nr]);
if (ret)
count = ret;
mutex_unlock(&data->update_lock);
return count;
}
static ssize_t adt7410_show_t_hyst(struct device *dev,
struct device_attribute *da,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct adt7410_data *data;
int nr = attr->index;
int hyst;
data = adt7410_update_device(dev);
if (IS_ERR(data))
return PTR_ERR(data);
hyst = (data->hyst & ADT7410_T_HYST_MASK) * 1000;
/*
* hysteresis is stored as a 4 bit offset in the device, convert it
* to an absolute value
*/
if (nr == 2) /* min has positive offset, others have negative */
hyst = -hyst;
return sprintf(buf, "%d\n",
ADT7410_REG_TO_TEMP(data, data->temp[nr]) - hyst);
}
static ssize_t adt7410_set_t_hyst(struct device *dev,
struct device_attribute *da,
const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct adt7410_data *data = i2c_get_clientdata(client);
int limit, ret;
long hyst;
ret = kstrtol(buf, 10, &hyst);
if (ret)
return ret;
/* convert absolute hysteresis value to a 4 bit delta value */
limit = ADT7410_REG_TO_TEMP(data, data->temp[1]);
hyst = clamp_val(hyst, ADT7410_TEMP_MIN, ADT7410_TEMP_MAX);
data->hyst = clamp_val(DIV_ROUND_CLOSEST(limit - hyst, 1000), 0,
ADT7410_T_HYST_MASK);
ret = i2c_smbus_write_byte_data(client, ADT7410_T_HYST, data->hyst);
if (ret)
return ret;
return count;
}
static ssize_t adt7410_show_alarm(struct device *dev,
struct device_attribute *da,
char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
int ret;
ret = i2c_smbus_read_byte_data(client, ADT7410_STATUS);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", !!(ret & attr->index));
}
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, adt7410_show_temp, NULL, 0);
static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
adt7410_show_temp, adt7410_set_temp, 1);
static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO,
adt7410_show_temp, adt7410_set_temp, 2);
static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO,
adt7410_show_temp, adt7410_set_temp, 3);
static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
adt7410_show_t_hyst, adt7410_set_t_hyst, 1);
static SENSOR_DEVICE_ATTR(temp1_min_hyst, S_IRUGO,
adt7410_show_t_hyst, NULL, 2);
static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO,
adt7410_show_t_hyst, NULL, 3);
static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, adt7410_show_alarm,
NULL, ADT7410_STAT_T_LOW);
static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, adt7410_show_alarm,
NULL, ADT7410_STAT_T_HIGH);
static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, adt7410_show_alarm,
NULL, ADT7410_STAT_T_CRIT);
static struct attribute *adt7410_attributes[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr,
&sensor_dev_attr_temp1_min.dev_attr.attr,
&sensor_dev_attr_temp1_crit.dev_attr.attr,
&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
&sensor_dev_attr_temp1_min_hyst.dev_attr.attr,
&sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
NULL
};
static const struct attribute_group adt7410_group = {
.attrs = adt7410_attributes,
};
/*-----------------------------------------------------------------------*/
/* device probe and removal */
static int adt7410_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct adt7410_data *data;
int ret;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
return -ENODEV;
data = devm_kzalloc(&client->dev, sizeof(struct adt7410_data),
GFP_KERNEL);
if (!data)
return -ENOMEM;
i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
/* configure as specified */
ret = i2c_smbus_read_byte_data(client, ADT7410_CONFIG);
if (ret < 0) {
dev_dbg(&client->dev, "Can't read config? %d\n", ret);
return ret;
}
data->oldconfig = ret;
/*
* Set to 16 bit resolution, continous conversion and comparator mode.
*/
ret &= ~ADT7410_MODE_MASK;
data->config = ret | ADT7410_FULL | ADT7410_RESOLUTION |
ADT7410_EVENT_MODE;
if (data->config != data->oldconfig) {
ret = i2c_smbus_write_byte_data(client, ADT7410_CONFIG,
data->config);
if (ret)
return ret;
}
dev_dbg(&client->dev, "Config %02x\n", data->config);
/* Register sysfs hooks */
ret = sysfs_create_group(&client->dev.kobj, &adt7410_group);
if (ret)
goto exit_restore;
data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) {
ret = PTR_ERR(data->hwmon_dev);
goto exit_remove;
}
dev_info(&client->dev, "sensor '%s'\n", client->name);
return 0;
exit_remove:
sysfs_remove_group(&client->dev.kobj, &adt7410_group);
exit_restore:
i2c_smbus_write_byte_data(client, ADT7410_CONFIG, data->oldconfig);
return ret;
return adt7x10_probe(&client->dev, NULL, client->irq, &adt7410_i2c_ops);
}
static int adt7410_remove(struct i2c_client *client)
static int adt7410_i2c_remove(struct i2c_client *client)
{
struct adt7410_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &adt7410_group);
if (data->oldconfig != data->config)
i2c_smbus_write_byte_data(client, ADT7410_CONFIG,
data->oldconfig);
return 0;
return adt7x10_remove(&client->dev, client->irq);
}
static const struct i2c_device_id adt7410_ids[] = {
{ "adt7410", adt7410, },
{ "adt7420", adt7410, },
{ /* LIST END */ }
{ "adt7410", 0 },
{ "adt7420", 0 },
{}
};
MODULE_DEVICE_TABLE(i2c, adt7410_ids);
#ifdef CONFIG_PM_SLEEP
static int adt7410_suspend(struct device *dev)
{
int ret;
struct i2c_client *client = to_i2c_client(dev);
struct adt7410_data *data = i2c_get_clientdata(client);
ret = i2c_smbus_write_byte_data(client, ADT7410_CONFIG,
data->config | ADT7410_PD);
return ret;
}
static int adt7410_resume(struct device *dev)
{
int ret;
struct i2c_client *client = to_i2c_client(dev);
struct adt7410_data *data = i2c_get_clientdata(client);
ret = i2c_smbus_write_byte_data(client, ADT7410_CONFIG, data->config);
return ret;
}
static SIMPLE_DEV_PM_OPS(adt7410_dev_pm_ops, adt7410_suspend, adt7410_resume);
#define ADT7410_DEV_PM_OPS (&adt7410_dev_pm_ops)
#else
#define ADT7410_DEV_PM_OPS NULL
#endif /* CONFIG_PM */
static struct i2c_driver adt7410_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = "adt7410",
.pm = ADT7410_DEV_PM_OPS,
.pm = ADT7X10_DEV_PM_OPS,
},
.probe = adt7410_probe,
.remove = adt7410_remove,
.probe = adt7410_i2c_probe,
.remove = adt7410_i2c_remove,
.id_table = adt7410_ids,
.address_list = I2C_ADDRS(0x48, 0x49, 0x4a, 0x4b),
};
module_i2c_driver(adt7410_driver);
MODULE_AUTHOR("Hartmut Knaack");
MODULE_DESCRIPTION("ADT7410/ADT7420 driver");
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("ADT7410/AD7420 driver");
MODULE_LICENSE("GPL");

View file

@ -259,15 +259,17 @@ static int adt7411_detect(struct i2c_client *client,
val = i2c_smbus_read_byte_data(client, ADT7411_REG_MANUFACTURER_ID);
if (val < 0 || val != ADT7411_MANUFACTURER_ID) {
dev_dbg(&client->dev, "Wrong manufacturer ID. Got %d, "
"expected %d\n", val, ADT7411_MANUFACTURER_ID);
dev_dbg(&client->dev,
"Wrong manufacturer ID. Got %d, expected %d\n",
val, ADT7411_MANUFACTURER_ID);
return -ENODEV;
}
val = i2c_smbus_read_byte_data(client, ADT7411_REG_DEVICE_ID);
if (val < 0 || val != ADT7411_DEVICE_ID) {
dev_dbg(&client->dev, "Wrong device ID. Got %d, "
"expected %d\n", val, ADT7411_DEVICE_ID);
dev_dbg(&client->dev,
"Wrong device ID. Got %d, expected %d\n",
val, ADT7411_DEVICE_ID);
return -ENODEV;
}

511
drivers/hwmon/adt7x10.c Normal file
View file

@ -0,0 +1,511 @@
/*
* adt7x10.c - Part of lm_sensors, Linux kernel modules for hardware
* monitoring
* This driver handles the ADT7410 and compatible digital temperature sensors.
* Hartmut Knaack <knaack.h@gmx.de> 2012-07-22
* based on lm75.c by Frodo Looijaard <frodol@dds.nl>
* and adt7410.c from iio-staging by Sonic Zhang <sonic.zhang@analog.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 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/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include "adt7x10.h"
/*
* ADT7X10 status
*/
#define ADT7X10_STAT_T_LOW (1 << 4)
#define ADT7X10_STAT_T_HIGH (1 << 5)
#define ADT7X10_STAT_T_CRIT (1 << 6)
#define ADT7X10_STAT_NOT_RDY (1 << 7)
/*
* ADT7X10 config
*/
#define ADT7X10_FAULT_QUEUE_MASK (1 << 0 | 1 << 1)
#define ADT7X10_CT_POLARITY (1 << 2)
#define ADT7X10_INT_POLARITY (1 << 3)
#define ADT7X10_EVENT_MODE (1 << 4)
#define ADT7X10_MODE_MASK (1 << 5 | 1 << 6)
#define ADT7X10_FULL (0 << 5 | 0 << 6)
#define ADT7X10_PD (1 << 5 | 1 << 6)
#define ADT7X10_RESOLUTION (1 << 7)
/*
* ADT7X10 masks
*/
#define ADT7X10_T13_VALUE_MASK 0xFFF8
#define ADT7X10_T_HYST_MASK 0xF
/* straight from the datasheet */
#define ADT7X10_TEMP_MIN (-55000)
#define ADT7X10_TEMP_MAX 150000
/* Each client has this additional data */
struct adt7x10_data {
const struct adt7x10_ops *ops;
const char *name;
struct device *hwmon_dev;
struct mutex update_lock;
u8 config;
u8 oldconfig;
bool valid; /* true if registers valid */
unsigned long last_updated; /* In jiffies */
s16 temp[4]; /* Register values,
0 = input
1 = high
2 = low
3 = critical */
u8 hyst; /* hysteresis offset */
};
static int adt7x10_read_byte(struct device *dev, u8 reg)
{
struct adt7x10_data *d = dev_get_drvdata(dev);
return d->ops->read_byte(dev, reg);
}
static int adt7x10_write_byte(struct device *dev, u8 reg, u8 data)
{
struct adt7x10_data *d = dev_get_drvdata(dev);
return d->ops->write_byte(dev, reg, data);
}
static int adt7x10_read_word(struct device *dev, u8 reg)
{
struct adt7x10_data *d = dev_get_drvdata(dev);
return d->ops->read_word(dev, reg);
}
static int adt7x10_write_word(struct device *dev, u8 reg, u16 data)
{
struct adt7x10_data *d = dev_get_drvdata(dev);
return d->ops->write_word(dev, reg, data);
}
static const u8 ADT7X10_REG_TEMP[4] = {
ADT7X10_TEMPERATURE, /* input */
ADT7X10_T_ALARM_HIGH, /* high */
ADT7X10_T_ALARM_LOW, /* low */
ADT7X10_T_CRIT, /* critical */
};
static irqreturn_t adt7x10_irq_handler(int irq, void *private)
{
struct device *dev = private;
int status;
status = adt7x10_read_byte(dev, ADT7X10_STATUS);
if (status < 0)
return IRQ_HANDLED;
if (status & ADT7X10_STAT_T_HIGH)
sysfs_notify(&dev->kobj, NULL, "temp1_max_alarm");
if (status & ADT7X10_STAT_T_LOW)
sysfs_notify(&dev->kobj, NULL, "temp1_min_alarm");
if (status & ADT7X10_STAT_T_CRIT)
sysfs_notify(&dev->kobj, NULL, "temp1_crit_alarm");
return IRQ_HANDLED;
}
static int adt7x10_temp_ready(struct device *dev)
{
int i, status;
for (i = 0; i < 6; i++) {
status = adt7x10_read_byte(dev, ADT7X10_STATUS);
if (status < 0)
return status;
if (!(status & ADT7X10_STAT_NOT_RDY))
return 0;
msleep(60);
}
return -ETIMEDOUT;
}
static int adt7x10_update_temp(struct device *dev)
{
struct adt7x10_data *data = dev_get_drvdata(dev);
int ret = 0;
mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|| !data->valid) {
int temp;
dev_dbg(dev, "Starting update\n");
ret = adt7x10_temp_ready(dev); /* check for new value */
if (ret)
goto abort;
temp = adt7x10_read_word(dev, ADT7X10_REG_TEMP[0]);
if (temp < 0) {
ret = temp;
dev_dbg(dev, "Failed to read value: reg %d, error %d\n",
ADT7X10_REG_TEMP[0], ret);
goto abort;
}
data->temp[0] = temp;
data->last_updated = jiffies;
data->valid = true;
}
abort:
mutex_unlock(&data->update_lock);
return ret;
}
static int adt7x10_fill_cache(struct device *dev)
{
struct adt7x10_data *data = dev_get_drvdata(dev);
int ret;
int i;
for (i = 1; i < ARRAY_SIZE(data->temp); i++) {
ret = adt7x10_read_word(dev, ADT7X10_REG_TEMP[i]);
if (ret < 0) {
dev_dbg(dev, "Failed to read value: reg %d, error %d\n",
ADT7X10_REG_TEMP[i], ret);
return ret;
}
data->temp[i] = ret;
}
ret = adt7x10_read_byte(dev, ADT7X10_T_HYST);
if (ret < 0) {
dev_dbg(dev, "Failed to read value: reg %d, error %d\n",
ADT7X10_T_HYST, ret);
return ret;
}
data->hyst = ret;
return 0;
}
static s16 ADT7X10_TEMP_TO_REG(long temp)
{
return DIV_ROUND_CLOSEST(clamp_val(temp, ADT7X10_TEMP_MIN,
ADT7X10_TEMP_MAX) * 128, 1000);
}
static int ADT7X10_REG_TO_TEMP(struct adt7x10_data *data, s16 reg)
{
/* in 13 bit mode, bits 0-2 are status flags - mask them out */
if (!(data->config & ADT7X10_RESOLUTION))
reg &= ADT7X10_T13_VALUE_MASK;
/*
* temperature is stored in twos complement format, in steps of
* 1/128°C
*/
return DIV_ROUND_CLOSEST(reg * 1000, 128);
}
/*-----------------------------------------------------------------------*/
/* sysfs attributes for hwmon */
static ssize_t adt7x10_show_temp(struct device *dev,
struct device_attribute *da,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct adt7x10_data *data = dev_get_drvdata(dev);
if (attr->index == 0) {
int ret;
ret = adt7x10_update_temp(dev);
if (ret)
return ret;
}
return sprintf(buf, "%d\n", ADT7X10_REG_TO_TEMP(data,
data->temp[attr->index]));
}
static ssize_t adt7x10_set_temp(struct device *dev,
struct device_attribute *da,
const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct adt7x10_data *data = dev_get_drvdata(dev);
int nr = attr->index;
long temp;
int ret;
ret = kstrtol(buf, 10, &temp);
if (ret)
return ret;
mutex_lock(&data->update_lock);
data->temp[nr] = ADT7X10_TEMP_TO_REG(temp);
ret = adt7x10_write_word(dev, ADT7X10_REG_TEMP[nr], data->temp[nr]);
if (ret)
count = ret;
mutex_unlock(&data->update_lock);
return count;
}
static ssize_t adt7x10_show_t_hyst(struct device *dev,
struct device_attribute *da,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct adt7x10_data *data = dev_get_drvdata(dev);
int nr = attr->index;
int hyst;
hyst = (data->hyst & ADT7X10_T_HYST_MASK) * 1000;
/*
* hysteresis is stored as a 4 bit offset in the device, convert it
* to an absolute value
*/
if (nr == 2) /* min has positive offset, others have negative */
hyst = -hyst;
return sprintf(buf, "%d\n",
ADT7X10_REG_TO_TEMP(data, data->temp[nr]) - hyst);
}
static ssize_t adt7x10_set_t_hyst(struct device *dev,
struct device_attribute *da,
const char *buf, size_t count)
{
struct adt7x10_data *data = dev_get_drvdata(dev);
int limit, ret;
long hyst;
ret = kstrtol(buf, 10, &hyst);
if (ret)
return ret;
/* convert absolute hysteresis value to a 4 bit delta value */
limit = ADT7X10_REG_TO_TEMP(data, data->temp[1]);
hyst = clamp_val(hyst, ADT7X10_TEMP_MIN, ADT7X10_TEMP_MAX);
data->hyst = clamp_val(DIV_ROUND_CLOSEST(limit - hyst, 1000),
0, ADT7X10_T_HYST_MASK);
ret = adt7x10_write_byte(dev, ADT7X10_T_HYST, data->hyst);
if (ret)
return ret;
return count;
}
static ssize_t adt7x10_show_alarm(struct device *dev,
struct device_attribute *da,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
int ret;
ret = adt7x10_read_byte(dev, ADT7X10_STATUS);
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", !!(ret & attr->index));
}
static ssize_t adt7x10_show_name(struct device *dev,
struct device_attribute *da,
char *buf)
{
struct adt7x10_data *data = dev_get_drvdata(dev);
return sprintf(buf, "%s\n", data->name);
}
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, adt7x10_show_temp, NULL, 0);
static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
adt7x10_show_temp, adt7x10_set_temp, 1);
static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO,
adt7x10_show_temp, adt7x10_set_temp, 2);
static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO,
adt7x10_show_temp, adt7x10_set_temp, 3);
static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
adt7x10_show_t_hyst, adt7x10_set_t_hyst, 1);
static SENSOR_DEVICE_ATTR(temp1_min_hyst, S_IRUGO,
adt7x10_show_t_hyst, NULL, 2);
static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO,
adt7x10_show_t_hyst, NULL, 3);
static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, adt7x10_show_alarm,
NULL, ADT7X10_STAT_T_LOW);
static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, adt7x10_show_alarm,
NULL, ADT7X10_STAT_T_HIGH);
static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, adt7x10_show_alarm,
NULL, ADT7X10_STAT_T_CRIT);
static DEVICE_ATTR(name, S_IRUGO, adt7x10_show_name, NULL);
static struct attribute *adt7x10_attributes[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr,
&sensor_dev_attr_temp1_min.dev_attr.attr,
&sensor_dev_attr_temp1_crit.dev_attr.attr,
&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
&sensor_dev_attr_temp1_min_hyst.dev_attr.attr,
&sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
NULL
};
static const struct attribute_group adt7x10_group = {
.attrs = adt7x10_attributes,
};
int adt7x10_probe(struct device *dev, const char *name, int irq,
const struct adt7x10_ops *ops)
{
struct adt7x10_data *data;
int ret;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
data->ops = ops;
data->name = name;
dev_set_drvdata(dev, data);
mutex_init(&data->update_lock);
/* configure as specified */
ret = adt7x10_read_byte(dev, ADT7X10_CONFIG);
if (ret < 0) {
dev_dbg(dev, "Can't read config? %d\n", ret);
return ret;
}
data->oldconfig = ret;
/*
* Set to 16 bit resolution, continous conversion and comparator mode.
*/
data->config = data->oldconfig;
data->config &= ~(ADT7X10_MODE_MASK | ADT7X10_CT_POLARITY |
ADT7X10_INT_POLARITY);
data->config |= ADT7X10_FULL | ADT7X10_RESOLUTION | ADT7X10_EVENT_MODE;
if (data->config != data->oldconfig) {
ret = adt7x10_write_byte(dev, ADT7X10_CONFIG, data->config);
if (ret)
return ret;
}
dev_dbg(dev, "Config %02x\n", data->config);
ret = adt7x10_fill_cache(dev);
if (ret)
goto exit_restore;
/* Register sysfs hooks */
ret = sysfs_create_group(&dev->kobj, &adt7x10_group);
if (ret)
goto exit_restore;
/*
* The I2C device will already have it's own 'name' attribute, but for
* the SPI device we need to register it. name will only be non NULL if
* the device doesn't register the 'name' attribute on its own.
*/
if (name) {
ret = device_create_file(dev, &dev_attr_name);
if (ret)
goto exit_remove;
}
data->hwmon_dev = hwmon_device_register(dev);
if (IS_ERR(data->hwmon_dev)) {
ret = PTR_ERR(data->hwmon_dev);
goto exit_remove_name;
}
if (irq > 0) {
ret = request_threaded_irq(irq, NULL, adt7x10_irq_handler,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
dev_name(dev), dev);
if (ret)
goto exit_hwmon_device_unregister;
}
return 0;
exit_hwmon_device_unregister:
hwmon_device_unregister(data->hwmon_dev);
exit_remove_name:
if (name)
device_remove_file(dev, &dev_attr_name);
exit_remove:
sysfs_remove_group(&dev->kobj, &adt7x10_group);
exit_restore:
adt7x10_write_byte(dev, ADT7X10_CONFIG, data->oldconfig);
return ret;
}
EXPORT_SYMBOL_GPL(adt7x10_probe);
int adt7x10_remove(struct device *dev, int irq)
{
struct adt7x10_data *data = dev_get_drvdata(dev);
if (irq > 0)
free_irq(irq, dev);
hwmon_device_unregister(data->hwmon_dev);
if (data->name)
device_remove_file(dev, &dev_attr_name);
sysfs_remove_group(&dev->kobj, &adt7x10_group);
if (data->oldconfig != data->config)
adt7x10_write_byte(dev, ADT7X10_CONFIG, data->oldconfig);
return 0;
}
EXPORT_SYMBOL_GPL(adt7x10_remove);
#ifdef CONFIG_PM_SLEEP
static int adt7x10_suspend(struct device *dev)
{
struct adt7x10_data *data = dev_get_drvdata(dev);
return adt7x10_write_byte(dev, ADT7X10_CONFIG,
data->config | ADT7X10_PD);
}
static int adt7x10_resume(struct device *dev)
{
struct adt7x10_data *data = dev_get_drvdata(dev);
return adt7x10_write_byte(dev, ADT7X10_CONFIG, data->config);
}
SIMPLE_DEV_PM_OPS(adt7x10_dev_pm_ops, adt7x10_suspend, adt7x10_resume);
EXPORT_SYMBOL_GPL(adt7x10_dev_pm_ops);
#endif /* CONFIG_PM_SLEEP */
MODULE_AUTHOR("Hartmut Knaack");
MODULE_DESCRIPTION("ADT7410/ADT7420, ADT7310/ADT7320 common code");
MODULE_LICENSE("GPL");

37
drivers/hwmon/adt7x10.h Normal file
View file

@ -0,0 +1,37 @@
#ifndef __HWMON_ADT7X10_H__
#define __HWMON_ADT7X10_H__
#include <linux/types.h>
#include <linux/pm.h>
/* ADT7410 registers definition */
#define ADT7X10_TEMPERATURE 0
#define ADT7X10_STATUS 2
#define ADT7X10_CONFIG 3
#define ADT7X10_T_ALARM_HIGH 4
#define ADT7X10_T_ALARM_LOW 6
#define ADT7X10_T_CRIT 8
#define ADT7X10_T_HYST 0xA
#define ADT7X10_ID 0xB
struct device;
struct adt7x10_ops {
int (*read_byte)(struct device *, u8 reg);
int (*write_byte)(struct device *, u8 reg, u8 data);
int (*read_word)(struct device *, u8 reg);
int (*write_word)(struct device *, u8 reg, u16 data);
};
int adt7x10_probe(struct device *dev, const char *name, int irq,
const struct adt7x10_ops *ops);
int adt7x10_remove(struct device *dev, int irq);
#ifdef CONFIG_PM_SLEEP
extern const struct dev_pm_ops adt7x10_dev_pm_ops;
#define ADT7X10_DEV_PM_OPS (&adt7x10_dev_pm_ops)
#else
#define ADT7X10_DEV_PM_OPS NULL
#endif
#endif

View file

@ -922,7 +922,7 @@ static void applesmc_brightness_set(struct led_classdev *led_cdev,
ret = queue_work(applesmc_led_wq, &backlight_work);
if (debug && (!ret))
printk(KERN_DEBUG "applesmc: work was already on the queue.\n");
dev_dbg(led_cdev->dev, "work was already on the queue.\n");
}
static ssize_t applesmc_key_count_show(struct device *dev,

View file

@ -55,8 +55,8 @@ static const unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END };
static unsigned short force_subclients[4];
module_param_array(force_subclients, short, NULL, 0);
MODULE_PARM_DESC(force_subclients, "List of subclient addresses: "
"{bus, clientaddr, subclientaddr1, subclientaddr2}");
MODULE_PARM_DESC(force_subclients,
"List of subclient addresses: {bus, clientaddr, subclientaddr1, subclientaddr2}");
/* Voltage IN registers 0-6 */
#define ASB100_REG_IN(nr) (0x20 + (nr))
@ -689,8 +689,8 @@ static int asb100_detect_subclients(struct i2c_client *client)
for (i = 2; i <= 3; i++) {
if (force_subclients[i] < 0x48 ||
force_subclients[i] > 0x4f) {
dev_err(&client->dev, "invalid subclient "
"address %d; must be 0x48-0x4f\n",
dev_err(&client->dev,
"invalid subclient address %d; must be 0x48-0x4f\n",
force_subclients[i]);
err = -ENODEV;
goto ERROR_SC_2;
@ -708,24 +708,27 @@ static int asb100_detect_subclients(struct i2c_client *client)
}
if (sc_addr[0] == sc_addr[1]) {
dev_err(&client->dev, "duplicate addresses 0x%x "
"for subclients\n", sc_addr[0]);
dev_err(&client->dev,
"duplicate addresses 0x%x for subclients\n",
sc_addr[0]);
err = -ENODEV;
goto ERROR_SC_2;
}
data->lm75[0] = i2c_new_dummy(adapter, sc_addr[0]);
if (!data->lm75[0]) {
dev_err(&client->dev, "subclient %d registration "
"at address 0x%x failed.\n", 1, sc_addr[0]);
dev_err(&client->dev,
"subclient %d registration at address 0x%x failed.\n",
1, sc_addr[0]);
err = -ENOMEM;
goto ERROR_SC_2;
}
data->lm75[1] = i2c_new_dummy(adapter, sc_addr[1]);
if (!data->lm75[1]) {
dev_err(&client->dev, "subclient %d registration "
"at address 0x%x failed.\n", 2, sc_addr[1]);
dev_err(&client->dev,
"subclient %d registration at address 0x%x failed.\n",
2, sc_addr[1]);
err = -ENOMEM;
goto ERROR_SC_3;
}

View file

@ -159,12 +159,12 @@ static inline int write_byte(struct i2c_client *client, u8 reg, u8 data)
* and retrieval of like parameters.
*/
#define SETUP_SHOW_data_param(d, a) \
#define SETUP_SHOW_DATA_PARAM(d, a) \
struct sensor_device_attribute *sda = to_sensor_dev_attr(a); \
struct asc7621_data *data = asc7621_update_device(d); \
struct asc7621_param *param = to_asc7621_param(sda)
#define SETUP_STORE_data_param(d, a) \
#define SETUP_STORE_DATA_PARAM(d, a) \
struct sensor_device_attribute *sda = to_sensor_dev_attr(a); \
struct i2c_client *client = to_i2c_client(d); \
struct asc7621_data *data = i2c_get_clientdata(client); \
@ -177,7 +177,7 @@ static inline int write_byte(struct i2c_client *client, u8 reg, u8 data)
static ssize_t show_u8(struct device *dev, struct device_attribute *attr,
char *buf)
{
SETUP_SHOW_data_param(dev, attr);
SETUP_SHOW_DATA_PARAM(dev, attr);
return sprintf(buf, "%u\n", data->reg[param->msb[0]]);
}
@ -185,7 +185,7 @@ static ssize_t show_u8(struct device *dev, struct device_attribute *attr,
static ssize_t store_u8(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
SETUP_STORE_data_param(dev, attr);
SETUP_STORE_DATA_PARAM(dev, attr);
long reqval;
if (kstrtol(buf, 10, &reqval))
@ -206,7 +206,7 @@ static ssize_t store_u8(struct device *dev, struct device_attribute *attr,
static ssize_t show_bitmask(struct device *dev,
struct device_attribute *attr, char *buf)
{
SETUP_SHOW_data_param(dev, attr);
SETUP_SHOW_DATA_PARAM(dev, attr);
return sprintf(buf, "%u\n",
(data->reg[param->msb[0]] >> param->
@ -217,7 +217,7 @@ static ssize_t store_bitmask(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
SETUP_STORE_data_param(dev, attr);
SETUP_STORE_DATA_PARAM(dev, attr);
long reqval;
u8 currval;
@ -246,7 +246,7 @@ static ssize_t store_bitmask(struct device *dev,
static ssize_t show_fan16(struct device *dev,
struct device_attribute *attr, char *buf)
{
SETUP_SHOW_data_param(dev, attr);
SETUP_SHOW_DATA_PARAM(dev, attr);
u16 regval;
mutex_lock(&data->update_lock);
@ -262,7 +262,7 @@ static ssize_t store_fan16(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
SETUP_STORE_data_param(dev, attr);
SETUP_STORE_DATA_PARAM(dev, attr);
long reqval;
if (kstrtol(buf, 10, &reqval))
@ -307,7 +307,7 @@ static int asc7621_in_scaling[] = {
static ssize_t show_in10(struct device *dev, struct device_attribute *attr,
char *buf)
{
SETUP_SHOW_data_param(dev, attr);
SETUP_SHOW_DATA_PARAM(dev, attr);
u16 regval;
u8 nr = sda->index;
@ -325,7 +325,7 @@ static ssize_t show_in10(struct device *dev, struct device_attribute *attr,
static ssize_t show_in8(struct device *dev, struct device_attribute *attr,
char *buf)
{
SETUP_SHOW_data_param(dev, attr);
SETUP_SHOW_DATA_PARAM(dev, attr);
u8 nr = sda->index;
return sprintf(buf, "%u\n",
@ -336,7 +336,7 @@ static ssize_t show_in8(struct device *dev, struct device_attribute *attr,
static ssize_t store_in8(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
SETUP_STORE_data_param(dev, attr);
SETUP_STORE_DATA_PARAM(dev, attr);
long reqval;
u8 nr = sda->index;
@ -360,7 +360,7 @@ static ssize_t store_in8(struct device *dev, struct device_attribute *attr,
static ssize_t show_temp8(struct device *dev,
struct device_attribute *attr, char *buf)
{
SETUP_SHOW_data_param(dev, attr);
SETUP_SHOW_DATA_PARAM(dev, attr);
return sprintf(buf, "%d\n", ((s8) data->reg[param->msb[0]]) * 1000);
}
@ -369,7 +369,7 @@ static ssize_t store_temp8(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
SETUP_STORE_data_param(dev, attr);
SETUP_STORE_DATA_PARAM(dev, attr);
long reqval;
s8 temp;
@ -397,7 +397,7 @@ static ssize_t store_temp8(struct device *dev,
static ssize_t show_temp10(struct device *dev,
struct device_attribute *attr, char *buf)
{
SETUP_SHOW_data_param(dev, attr);
SETUP_SHOW_DATA_PARAM(dev, attr);
u8 msb, lsb;
int temp;
@ -414,7 +414,7 @@ static ssize_t show_temp10(struct device *dev,
static ssize_t show_temp62(struct device *dev,
struct device_attribute *attr, char *buf)
{
SETUP_SHOW_data_param(dev, attr);
SETUP_SHOW_DATA_PARAM(dev, attr);
u8 regval = data->reg[param->msb[0]];
int temp = ((s8) (regval & 0xfc) * 1000) + ((regval & 0x03) * 250);
@ -425,7 +425,7 @@ static ssize_t store_temp62(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
SETUP_STORE_data_param(dev, attr);
SETUP_STORE_DATA_PARAM(dev, attr);
long reqval, i, f;
s8 temp;
@ -459,7 +459,7 @@ static u32 asc7621_range_map[] = {
static ssize_t show_ap2_temp(struct device *dev,
struct device_attribute *attr, char *buf)
{
SETUP_SHOW_data_param(dev, attr);
SETUP_SHOW_DATA_PARAM(dev, attr);
long auto_point1;
u8 regval;
int temp;
@ -479,7 +479,7 @@ static ssize_t store_ap2_temp(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
SETUP_STORE_data_param(dev, attr);
SETUP_STORE_DATA_PARAM(dev, attr);
long reqval, auto_point1;
int i;
u8 currval, newval = 0;
@ -510,7 +510,7 @@ static ssize_t store_ap2_temp(struct device *dev,
static ssize_t show_pwm_ac(struct device *dev,
struct device_attribute *attr, char *buf)
{
SETUP_SHOW_data_param(dev, attr);
SETUP_SHOW_DATA_PARAM(dev, attr);
u8 config, altbit, regval;
u8 map[] = {
0x01, 0x02, 0x04, 0x1f, 0x00, 0x06, 0x07, 0x10,
@ -530,7 +530,7 @@ static ssize_t store_pwm_ac(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
SETUP_STORE_data_param(dev, attr);
SETUP_STORE_DATA_PARAM(dev, attr);
unsigned long reqval;
u8 currval, config, altbit, newval;
u16 map[] = {
@ -569,7 +569,7 @@ static ssize_t store_pwm_ac(struct device *dev,
static ssize_t show_pwm_enable(struct device *dev,
struct device_attribute *attr, char *buf)
{
SETUP_SHOW_data_param(dev, attr);
SETUP_SHOW_DATA_PARAM(dev, attr);
u8 config, altbit, minoff, val, newval;
mutex_lock(&data->update_lock);
@ -599,7 +599,7 @@ static ssize_t store_pwm_enable(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
SETUP_STORE_data_param(dev, attr);
SETUP_STORE_DATA_PARAM(dev, attr);
long reqval;
u8 currval, config, altbit, newval, minoff = 255;
@ -659,7 +659,7 @@ static u32 asc7621_pwm_freq_map[] = {
static ssize_t show_pwm_freq(struct device *dev,
struct device_attribute *attr, char *buf)
{
SETUP_SHOW_data_param(dev, attr);
SETUP_SHOW_DATA_PARAM(dev, attr);
u8 regval =
(data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0];
@ -672,7 +672,7 @@ static ssize_t store_pwm_freq(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
SETUP_STORE_data_param(dev, attr);
SETUP_STORE_DATA_PARAM(dev, attr);
unsigned long reqval;
u8 currval, newval = 255;
int i;
@ -707,7 +707,7 @@ static u32 asc7621_pwm_auto_spinup_map[] = {
static ssize_t show_pwm_ast(struct device *dev,
struct device_attribute *attr, char *buf)
{
SETUP_SHOW_data_param(dev, attr);
SETUP_SHOW_DATA_PARAM(dev, attr);
u8 regval =
(data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0];
@ -721,7 +721,7 @@ static ssize_t store_pwm_ast(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
SETUP_STORE_data_param(dev, attr);
SETUP_STORE_DATA_PARAM(dev, attr);
long reqval;
u8 currval, newval = 255;
u32 i;
@ -756,7 +756,7 @@ static u32 asc7621_temp_smoothing_time_map[] = {
static ssize_t show_temp_st(struct device *dev,
struct device_attribute *attr, char *buf)
{
SETUP_SHOW_data_param(dev, attr);
SETUP_SHOW_DATA_PARAM(dev, attr);
u8 regval =
(data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0];
regval = clamp_val(regval, 0, 7);
@ -768,7 +768,7 @@ static ssize_t store_temp_st(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
SETUP_STORE_data_param(dev, attr);
SETUP_STORE_DATA_PARAM(dev, attr);
long reqval;
u8 currval, newval = 255;
u32 i;

View file

@ -411,8 +411,7 @@ static int __cpuinit chk_ucode_version(unsigned int cpu)
* fixed for stepping D0 (6EC).
*/
if (c->x86_model == 0xe && c->x86_mask < 0xc && c->microcode < 0x39) {
pr_err("Errata AE18 not fixed, update BIOS or "
"microcode of the CPU!\n");
pr_err("Errata AE18 not fixed, update BIOS or microcode of the CPU!\n");
return -ENODEV;
}
return 0;

View file

@ -43,19 +43,19 @@ static const char * const input_names[] = {
};
/* Conversion function for VDDOUT and VBAT */
static inline int volt_reg_to_mV(int value)
static inline int volt_reg_to_mv(int value)
{
return DIV_ROUND_CLOSEST(value * 1000, 512) + 2500;
}
/* Conversion function for ADC channels 4, 5 and 6 */
static inline int input_reg_to_mV(int value)
static inline int input_reg_to_mv(int value)
{
return DIV_ROUND_CLOSEST(value * 2500, 1023);
}
/* Conversion function for VBBAT */
static inline int vbbat_reg_to_mV(int value)
static inline int vbbat_reg_to_mv(int value)
{
return DIV_ROUND_CLOSEST(value * 2500, 512);
}
@ -96,7 +96,7 @@ static ssize_t da9052_read_vddout(struct device *dev,
goto hwmon_err;
mutex_unlock(&hwmon->hwmon_lock);
return sprintf(buf, "%d\n", volt_reg_to_mV(vdd));
return sprintf(buf, "%d\n", volt_reg_to_mv(vdd));
hwmon_err_release:
da9052_disable_vddout_channel(hwmon->da9052);
@ -137,7 +137,7 @@ static ssize_t da9052_read_vbat(struct device *dev,
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", volt_reg_to_mV(ret));
return sprintf(buf, "%d\n", volt_reg_to_mv(ret));
}
static ssize_t da9052_read_misc_channel(struct device *dev,
@ -152,7 +152,7 @@ static ssize_t da9052_read_misc_channel(struct device *dev,
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", input_reg_to_mV(ret));
return sprintf(buf, "%d\n", input_reg_to_mv(ret));
}
static ssize_t da9052_read_tjunc(struct device *dev,
@ -187,7 +187,7 @@ static ssize_t da9052_read_vbbat(struct device *dev,
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", vbbat_reg_to_mV(ret));
return sprintf(buf, "%d\n", vbbat_reg_to_mv(ret));
}
static ssize_t da9052_hwmon_show_name(struct device *dev,

View file

@ -119,7 +119,7 @@ static irqreturn_t da9055_auxadc_irq(int irq, void *irq_data)
}
/* Conversion function for VSYS and ADCINx */
static inline int volt_reg_to_mV(int value, int channel)
static inline int volt_reg_to_mv(int value, int channel)
{
if (channel == DA9055_ADC_VSYS)
return DIV_ROUND_CLOSEST(value * 1000, DA9055_VSYS_DIV) + 2500;
@ -168,7 +168,7 @@ static ssize_t da9055_read_auto_ch(struct device *dev,
mutex_unlock(&hwmon->hwmon_lock);
return sprintf(buf, "%d\n", volt_reg_to_mV(adc, channel));
return sprintf(buf, "%d\n", volt_reg_to_mv(adc, channel));
hwmon_err_release:
da9055_disable_auto_mode(hwmon->da9055, channel);

View file

@ -55,14 +55,16 @@ MODULE_PARM_DESC(force_id, "Override the detected device ID");
static bool probe_all_addr;
module_param(probe_all_addr, bool, 0);
MODULE_PARM_DESC(probe_all_addr, "Include probing of non-standard LPC "
"addresses");
MODULE_PARM_DESC(probe_all_addr,
"Include probing of non-standard LPC addresses");
/* Addresses to scan */
static const unsigned short normal_i2c[] = {0x2c, 0x2d, 0x2e, I2C_CLIENT_END};
enum chips { dme1737, sch5027, sch311x, sch5127 };
#define DO_REPORT "Please report to the driver maintainer."
/* ---------------------------------------------------------------------
* Registers
*
@ -566,9 +568,9 @@ static u8 dme1737_read(const struct dme1737_data *data, u8 reg)
val = i2c_smbus_read_byte_data(client, reg);
if (val < 0) {
dev_warn(&client->dev, "Read from register "
"0x%02x failed! Please report to the driver "
"maintainer.\n", reg);
dev_warn(&client->dev,
"Read from register 0x%02x failed! %s\n",
reg, DO_REPORT);
}
} else { /* ISA device */
outb(reg, data->addr);
@ -587,9 +589,9 @@ static s32 dme1737_write(const struct dme1737_data *data, u8 reg, u8 val)
res = i2c_smbus_write_byte_data(client, reg, val);
if (res < 0) {
dev_warn(&client->dev, "Write to register "
"0x%02x failed! Please report to the driver "
"maintainer.\n", reg);
dev_warn(&client->dev,
"Write to register 0x%02x failed! %s\n",
reg, DO_REPORT);
}
} else { /* ISA device */
outb(reg, data->addr);
@ -1167,8 +1169,8 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *attr,
/* Only valid for fan[1-4] */
if (!(val == 1 || val == 2 || val == 4)) {
count = -EINVAL;
dev_warn(dev, "Fan type value %ld not "
"supported. Choose one of 1, 2, or 4.\n",
dev_warn(dev,
"Fan type value %ld not supported. Choose one of 1, 2, or 4.\n",
val);
goto exit;
}
@ -1294,8 +1296,8 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
/* Only valid for pwm[1-3] */
if (val < 0 || val > 2) {
count = -EINVAL;
dev_warn(dev, "PWM enable %ld not "
"supported. Choose one of 0, 1, or 2.\n",
dev_warn(dev,
"PWM enable %ld not supported. Choose one of 0, 1, or 2.\n",
val);
goto exit;
}
@ -1399,8 +1401,8 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
if (!(val == 1 || val == 2 || val == 4 ||
val == 6 || val == 7)) {
count = -EINVAL;
dev_warn(dev, "PWM auto channels zone %ld "
"not supported. Choose one of 1, 2, 4, 6, "
dev_warn(dev,
"PWM auto channels zone %ld not supported. Choose one of 1, 2, 4, 6, "
"or 7.\n", val);
goto exit;
}
@ -2178,8 +2180,8 @@ static int dme1737_create_files(struct device *dev)
* selected attributes from read-only to read-writeable.
*/
if (data->config & 0x02) {
dev_info(dev, "Device is locked. Some attributes "
"will be read-only.\n");
dev_info(dev,
"Device is locked. Some attributes will be read-only.\n");
} else {
/* Change permissions of zone sysfs attributes */
dme1737_chmod_group(dev, &dme1737_zone_chmod_group,
@ -2247,9 +2249,8 @@ static int dme1737_init_device(struct device *dev)
/* Inform if part is not monitoring/started */
if (!(data->config & 0x01)) {
if (!force_start) {
dev_err(dev, "Device is not monitoring. "
"Use the force_start load parameter to "
"override.\n");
dev_err(dev,
"Device is not monitoring. Use the force_start load parameter to override.\n");
return -EFAULT;
}
@ -2289,8 +2290,8 @@ static int dme1737_init_device(struct device *dev)
*/
if (dme1737_i2c_get_features(0x2e, data) &&
dme1737_i2c_get_features(0x4e, data)) {
dev_warn(dev, "Failed to query Super-IO for optional "
"features.\n");
dev_warn(dev,
"Failed to query Super-IO for optional features.\n");
}
}
@ -2317,8 +2318,8 @@ static int dme1737_init_device(struct device *dev)
break;
}
dev_info(dev, "Optional features: pwm3=%s, pwm5=%s, pwm6=%s, "
"fan3=%s, fan4=%s, fan5=%s, fan6=%s.\n",
dev_info(dev,
"Optional features: pwm3=%s, pwm5=%s, pwm6=%s, fan3=%s, fan4=%s, fan5=%s, fan6=%s.\n",
(data->has_features & HAS_PWM(2)) ? "yes" : "no",
(data->has_features & HAS_PWM(4)) ? "yes" : "no",
(data->has_features & HAS_PWM(5)) ? "yes" : "no",
@ -2330,18 +2331,16 @@ static int dme1737_init_device(struct device *dev)
reg = dme1737_read(data, DME1737_REG_TACH_PWM);
/* Inform if fan-to-pwm mapping differs from the default */
if (client && reg != 0xa4) { /* I2C chip */
dev_warn(dev, "Non-standard fan to pwm mapping: "
"fan1->pwm%d, fan2->pwm%d, fan3->pwm%d, "
"fan4->pwm%d. Please report to the driver "
"maintainer.\n",
dev_warn(dev,
"Non-standard fan to pwm mapping: fan1->pwm%d, fan2->pwm%d, fan3->pwm%d, fan4->pwm%d. %s\n",
(reg & 0x03) + 1, ((reg >> 2) & 0x03) + 1,
((reg >> 4) & 0x03) + 1, ((reg >> 6) & 0x03) + 1);
((reg >> 4) & 0x03) + 1, ((reg >> 6) & 0x03) + 1,
DO_REPORT);
} else if (!client && reg != 0x24) { /* ISA chip */
dev_warn(dev, "Non-standard fan to pwm mapping: "
"fan1->pwm%d, fan2->pwm%d, fan3->pwm%d. "
"Please report to the driver maintainer.\n",
dev_warn(dev,
"Non-standard fan to pwm mapping: fan1->pwm%d, fan2->pwm%d, fan3->pwm%d. %s\n",
(reg & 0x03) + 1, ((reg >> 2) & 0x03) + 1,
((reg >> 4) & 0x03) + 1);
((reg >> 4) & 0x03) + 1, DO_REPORT);
}
/*
@ -2355,8 +2354,9 @@ static int dme1737_init_device(struct device *dev)
DME1737_REG_PWM_CONFIG(ix));
if ((data->has_features & HAS_PWM(ix)) &&
(PWM_EN_FROM_REG(data->pwm_config[ix]) == -1)) {
dev_info(dev, "Switching pwm%d to "
"manual mode.\n", ix + 1);
dev_info(dev,
"Switching pwm%d to manual mode.\n",
ix + 1);
data->pwm_config[ix] = PWM_EN_TO_REG(1,
data->pwm_config[ix]);
dme1737_write(data, DME1737_REG_PWM(ix), 0);

View file

@ -1350,8 +1350,7 @@ static void f71805f_init_device(struct f71805f_data *data)
reg = f71805f_read8(data, F71805F_REG_START);
if ((reg & 0x41) != 0x01) {
printk(KERN_DEBUG DRVNAME ": Starting monitoring "
"operations\n");
pr_debug("Starting monitoring operations\n");
f71805f_write8(data, F71805F_REG_START, (reg | 0x01) & ~0x40);
}

View file

@ -189,8 +189,8 @@ static void fam15h_power_init_data(struct pci_dev *f4,
/* result not allowed to be >= 256W */
if ((tmp >> 16) >= 256)
dev_warn(&f4->dev, "Bogus value for ProcessorPwrWatts "
"(processor_pwr_watts>=%u)\n",
dev_warn(&f4->dev,
"Bogus value for ProcessorPwrWatts (processor_pwr_watts>=%u)\n",
(unsigned int) (tmp >> 16));
/* convert to microWatt */

View file

@ -463,8 +463,9 @@ static ssize_t store_fan_div(struct device *dev, struct device_attribute
v = 3;
break;
default:
dev_err(dev, "fan_div value %lu not supported. "
"Choose one of 2, 4 or 8!\n", v);
dev_err(dev,
"fan_div value %lu not supported. Choose one of 2, 4 or 8!\n",
v);
return -EINVAL;
}
@ -1249,8 +1250,8 @@ static int fschmd_probe(struct i2c_client *client,
}
if (i == ARRAY_SIZE(watchdog_minors)) {
data->watchdog_miscdev.minor = 0;
dev_warn(&client->dev, "Couldn't register watchdog chardev "
"(due to no free minor)\n");
dev_warn(&client->dev,
"Couldn't register watchdog chardev (due to no free minor)\n");
}
mutex_unlock(&watchdog_data_mutex);

View file

@ -344,8 +344,9 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
val = 3;
break;
default:
dev_err(dev, "Invalid fan clock divider %lu, choose one "
"of 1, 2, 4 or 8\n", val);
dev_err(dev,
"Invalid fan clock divider %lu, choose one of 1, 2, 4 or 8\n",
val);
return -EINVAL;
}

View file

@ -105,10 +105,6 @@ static int fan_alarm_init(struct gpio_fan_data *fan_data,
if (err)
return err;
err = device_create_file(&pdev->dev, &dev_attr_fan1_alarm);
if (err)
return err;
/*
* If the alarm GPIO don't support interrupts, just leave
* without initializing the fail notification support.
@ -121,23 +117,9 @@ static int fan_alarm_init(struct gpio_fan_data *fan_data,
irq_set_irq_type(alarm_irq, IRQ_TYPE_EDGE_BOTH);
err = devm_request_irq(&pdev->dev, alarm_irq, fan_alarm_irq_handler,
IRQF_SHARED, "GPIO fan alarm", fan_data);
if (err)
goto err_free_sysfs;
return 0;
err_free_sysfs:
device_remove_file(&pdev->dev, &dev_attr_fan1_alarm);
return err;
}
static void fan_alarm_free(struct gpio_fan_data *fan_data)
{
struct platform_device *pdev = fan_data->pdev;
device_remove_file(&pdev->dev, &dev_attr_fan1_alarm);
}
/*
* Control GPIOs.
*/
@ -327,6 +309,12 @@ exit_unlock:
return ret;
}
static ssize_t show_name(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "gpio-fan\n");
}
static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm);
static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
show_pwm_enable, set_pwm_enable);
@ -336,8 +324,26 @@ static DEVICE_ATTR(fan1_max, S_IRUGO, show_rpm_max, NULL);
static DEVICE_ATTR(fan1_input, S_IRUGO, show_rpm, NULL);
static DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR, show_rpm, set_rpm);
static struct attribute *gpio_fan_ctrl_attributes[] = {
&dev_attr_pwm1.attr,
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
static umode_t gpio_fan_is_visible(struct kobject *kobj,
struct attribute *attr, int index)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct gpio_fan_data *data = dev_get_drvdata(dev);
if (index == 1 && !data->alarm)
return 0;
if (index > 1 && !data->ctrl)
return 0;
return attr->mode;
}
static struct attribute *gpio_fan_attributes[] = {
&dev_attr_name.attr,
&dev_attr_fan1_alarm.attr, /* 1 */
&dev_attr_pwm1.attr, /* 2 */
&dev_attr_pwm1_enable.attr,
&dev_attr_pwm1_mode.attr,
&dev_attr_fan1_input.attr,
@ -347,8 +353,9 @@ static struct attribute *gpio_fan_ctrl_attributes[] = {
NULL
};
static const struct attribute_group gpio_fan_ctrl_group = {
.attrs = gpio_fan_ctrl_attributes,
static const struct attribute_group gpio_fan_group = {
.attrs = gpio_fan_attributes,
.is_visible = gpio_fan_is_visible,
};
static int fan_ctrl_init(struct gpio_fan_data *fan_data,
@ -379,30 +386,9 @@ static int fan_ctrl_init(struct gpio_fan_data *fan_data,
if (fan_data->speed_index < 0)
return -ENODEV;
err = sysfs_create_group(&pdev->dev.kobj, &gpio_fan_ctrl_group);
return err;
return 0;
}
static void fan_ctrl_free(struct gpio_fan_data *fan_data)
{
struct platform_device *pdev = fan_data->pdev;
sysfs_remove_group(&pdev->dev.kobj, &gpio_fan_ctrl_group);
}
/*
* Platform driver.
*/
static ssize_t show_name(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "gpio-fan\n");
}
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
#ifdef CONFIG_OF_GPIO
/*
* Translate OpenFirmware node properties into platform_data
@ -546,38 +532,30 @@ static int gpio_fan_probe(struct platform_device *pdev)
/* Configure control GPIOs if available. */
if (pdata->ctrl && pdata->num_ctrl > 0) {
if (!pdata->speed || pdata->num_speed <= 1) {
err = -EINVAL;
goto err_free_alarm;
}
if (!pdata->speed || pdata->num_speed <= 1)
return -EINVAL;
err = fan_ctrl_init(fan_data, pdata);
if (err)
goto err_free_alarm;
return err;
}
err = device_create_file(&pdev->dev, &dev_attr_name);
err = sysfs_create_group(&pdev->dev.kobj, &gpio_fan_group);
if (err)
goto err_free_ctrl;
return err;
/* Make this driver part of hwmon class. */
fan_data->hwmon_dev = hwmon_device_register(&pdev->dev);
if (IS_ERR(fan_data->hwmon_dev)) {
err = PTR_ERR(fan_data->hwmon_dev);
goto err_remove_name;
goto err_remove;
}
dev_info(&pdev->dev, "GPIO fan initialized\n");
return 0;
err_remove_name:
device_remove_file(&pdev->dev, &dev_attr_name);
err_free_ctrl:
if (fan_data->ctrl)
fan_ctrl_free(fan_data);
err_free_alarm:
if (fan_data->alarm)
fan_alarm_free(fan_data);
err_remove:
sysfs_remove_group(&pdev->dev.kobj, &gpio_fan_group);
return err;
}
@ -586,11 +564,7 @@ static int gpio_fan_remove(struct platform_device *pdev)
struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
hwmon_device_unregister(fan_data->hwmon_dev);
device_remove_file(&pdev->dev, &dev_attr_name);
if (fan_data->alarm)
fan_alarm_free(fan_data);
if (fan_data->ctrl)
fan_ctrl_free(fan_data);
sysfs_remove_group(&pdev->dev.kobj, &gpio_fan_group);
return 0;
}
@ -619,7 +593,7 @@ static int gpio_fan_resume(struct device *dev)
}
static SIMPLE_DEV_PM_OPS(gpio_fan_pm, gpio_fan_suspend, gpio_fan_resume);
#define GPIO_FAN_PM &gpio_fan_pm
#define GPIO_FAN_PM (&gpio_fan_pm)
#else
#define GPIO_FAN_PM NULL
#endif

View file

@ -289,8 +289,9 @@ static int aem_init_ipmi_data(struct aem_ipmi_data *data, int iface,
err = ipmi_create_user(data->interface, &driver_data.ipmi_hndlrs,
data, &data->user);
if (err < 0) {
dev_err(bmc, "Unable to register user with IPMI "
"interface %d\n", data->interface);
dev_err(bmc,
"Unable to register user with IPMI interface %d\n",
data->interface);
return -EACCES;
}
@ -328,8 +329,8 @@ static void aem_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
struct aem_ipmi_data *data = user_msg_data;
if (msg->msgid != data->tx_msgid) {
dev_err(data->bmc_device, "Mismatch between received msgid "
"(%02x) and transmitted msgid (%02x)!\n",
dev_err(data->bmc_device,
"Mismatch between received msgid (%02x) and transmitted msgid (%02x)!\n",
(int)msg->msgid,
(int)data->tx_msgid);
ipmi_free_recv_msg(msg);
@ -575,8 +576,8 @@ static int aem_init_aem1_inst(struct aem_ipmi_data *probe, u8 module_handle)
/* Register with hwmon */
data->hwmon_dev = hwmon_device_register(&data->pdev->dev);
if (IS_ERR(data->hwmon_dev)) {
dev_err(&data->pdev->dev, "Unable to register hwmon "
"device for IPMI interface %d\n",
dev_err(&data->pdev->dev,
"Unable to register hwmon device for IPMI interface %d\n",
probe->interface);
res = PTR_ERR(data->hwmon_dev);
goto hwmon_reg_err;
@ -715,8 +716,8 @@ static int aem_init_aem2_inst(struct aem_ipmi_data *probe,
/* Register with hwmon */
data->hwmon_dev = hwmon_device_register(&data->pdev->dev);
if (IS_ERR(data->hwmon_dev)) {
dev_err(&data->pdev->dev, "Unable to register hwmon "
"device for IPMI interface %d\n",
dev_err(&data->pdev->dev,
"Unable to register hwmon device for IPMI interface %d\n",
probe->interface);
res = PTR_ERR(data->hwmon_dev);
goto hwmon_reg_err;
@ -768,8 +769,8 @@ static void aem_init_aem2(struct aem_ipmi_data *probe)
while (!aem_find_aem2(probe, &fi_resp, i)) {
if (fi_resp.major != 2) {
dev_err(probe->bmc_device, "Unknown AEM v%d; please "
"report this to the maintainer.\n",
dev_err(probe->bmc_device,
"Unknown AEM v%d; please report this to the maintainer.\n",
fi_resp.major);
i++;
continue;

View file

@ -163,8 +163,8 @@ static int ibmpex_ver_check(struct ibmpex_bmc_data *data)
data->sensor_major = data->rx_msg_data[0];
data->sensor_minor = data->rx_msg_data[1];
dev_info(data->bmc_device, "Found BMC with sensor interface "
"v%d.%d %d-%02d-%02d on interface %d\n",
dev_info(data->bmc_device,
"Found BMC with sensor interface v%d.%d %d-%02d-%02d on interface %d\n",
data->sensor_major,
data->sensor_minor,
extract_value(data->rx_msg_data, 2),
@ -478,8 +478,9 @@ static void ibmpex_register_bmc(int iface, struct device *dev)
err = ipmi_create_user(data->interface, &driver_data.ipmi_hndlrs,
data, &data->user);
if (err < 0) {
dev_err(dev, "Unable to register user with IPMI "
"interface %d\n", data->interface);
dev_err(dev,
"Unable to register user with IPMI interface %d\n",
data->interface);
goto out;
}
@ -501,8 +502,8 @@ static void ibmpex_register_bmc(int iface, struct device *dev)
data->hwmon_dev = hwmon_device_register(data->bmc_device);
if (IS_ERR(data->hwmon_dev)) {
dev_err(data->bmc_device, "Unable to register hwmon "
"device for IPMI interface %d\n",
dev_err(data->bmc_device,
"Unable to register hwmon device for IPMI interface %d\n",
data->interface);
goto out_user;
}
@ -567,8 +568,8 @@ static void ibmpex_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
struct ibmpex_bmc_data *data = (struct ibmpex_bmc_data *)user_msg_data;
if (msg->msgid != data->tx_msgid) {
dev_err(data->bmc_device, "Mismatch between received msgid "
"(%02x) and transmitted msgid (%02x)!\n",
dev_err(data->bmc_device,
"Mismatch between received msgid (%02x) and transmitted msgid (%02x)!\n",
(int)msg->msgid,
(int)data->tx_msgid);
ipmi_free_recv_msg(msg);

View file

@ -186,20 +186,20 @@ static ssize_t ina2xx_show_value(struct device *dev,
}
/* shunt voltage */
static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, \
ina2xx_show_value, NULL, INA2XX_SHUNT_VOLTAGE);
static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, ina2xx_show_value, NULL,
INA2XX_SHUNT_VOLTAGE);
/* bus voltage */
static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, \
ina2xx_show_value, NULL, INA2XX_BUS_VOLTAGE);
static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ina2xx_show_value, NULL,
INA2XX_BUS_VOLTAGE);
/* calculated current */
static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, \
ina2xx_show_value, NULL, INA2XX_CURRENT);
static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ina2xx_show_value, NULL,
INA2XX_CURRENT);
/* calculated power */
static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, \
ina2xx_show_value, NULL, INA2XX_POWER);
static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, ina2xx_show_value, NULL,
INA2XX_POWER);
/* pointers to created device attributes */
static struct attribute *ina2xx_attributes[] = {

View file

@ -1778,7 +1778,7 @@ static int __init it87_find(unsigned short *address,
superio_select(5);
sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
} else if (sio_data->type == it8783) {
int reg25, reg27, reg2A, reg2C, regEF;
int reg25, reg27, reg2a, reg2c, regef;
sio_data->skip_vid = 1; /* No VID */
@ -1786,15 +1786,15 @@ static int __init it87_find(unsigned short *address,
reg25 = superio_inb(IT87_SIO_GPIO1_REG);
reg27 = superio_inb(IT87_SIO_GPIO3_REG);
reg2A = superio_inb(IT87_SIO_PINX1_REG);
reg2C = superio_inb(IT87_SIO_PINX2_REG);
regEF = superio_inb(IT87_SIO_SPI_REG);
reg2a = superio_inb(IT87_SIO_PINX1_REG);
reg2c = superio_inb(IT87_SIO_PINX2_REG);
regef = superio_inb(IT87_SIO_SPI_REG);
/* Check if fan3 is there or not */
if ((reg27 & (1 << 0)) || !(reg2C & (1 << 2)))
if ((reg27 & (1 << 0)) || !(reg2c & (1 << 2)))
sio_data->skip_fan |= (1 << 2);
if ((reg25 & (1 << 4))
|| (!(reg2A & (1 << 1)) && (regEF & (1 << 0))))
|| (!(reg2a & (1 << 1)) && (regef & (1 << 0))))
sio_data->skip_pwm |= (1 << 2);
/* Check if fan2 is there or not */
@ -1804,7 +1804,7 @@ static int __init it87_find(unsigned short *address,
sio_data->skip_pwm |= (1 << 1);
/* VIN5 */
if ((reg27 & (1 << 0)) || (reg2C & (1 << 2)))
if ((reg27 & (1 << 0)) || (reg2c & (1 << 2)))
sio_data->skip_in |= (1 << 5); /* No VIN5 */
/* VIN6 */
@ -1829,18 +1829,18 @@ static int __init it87_find(unsigned short *address,
* not the case, and ask the user to report if the
* resulting voltage is sane.
*/
if (!(reg2C & (1 << 1))) {
reg2C |= (1 << 1);
superio_outb(IT87_SIO_PINX2_REG, reg2C);
if (!(reg2c & (1 << 1))) {
reg2c |= (1 << 1);
superio_outb(IT87_SIO_PINX2_REG, reg2c);
pr_notice("Routing internal VCCH5V to in7.\n");
}
pr_notice("in7 routed to internal voltage divider, with external pin disabled.\n");
pr_notice("Please report if it displays a reasonable voltage.\n");
}
if (reg2C & (1 << 0))
if (reg2c & (1 << 0))
sio_data->internal |= (1 << 0);
if (reg2C & (1 << 1))
if (reg2c & (1 << 1))
sio_data->internal |= (1 << 1);
sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;

View file

@ -200,8 +200,8 @@ static int k8temp_probe(struct pci_dev *pdev,
*/
if (model >= 0x40) {
data->swap_core_select = 1;
dev_warn(&pdev->dev, "Temperature readouts might be wrong - "
"check erratum #141\n");
dev_warn(&pdev->dev,
"Temperature readouts might be wrong - check erratum #141\n");
}
/*

View file

@ -386,8 +386,9 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *da,
data->fan_div[nr] = 3;
break;
default:
dev_err(dev, "fan_div value %ld not "
"supported. Choose one of 1, 2, 4 or 8!\n", val);
dev_err(dev,
"fan_div value %ld not supported. Choose one of 1, 2, 4 or 8!\n",
val);
mutex_unlock(&data->update_lock);
return -EINVAL;
}
@ -636,8 +637,9 @@ static int lm78_i2c_detect(struct i2c_client *client,
goto err_nodev;
if (lm78_alias_detect(client, i)) {
dev_dbg(&adapter->dev, "Device at 0x%02x appears to "
"be the same as ISA device\n", address);
dev_dbg(&adapter->dev,
"Device at 0x%02x appears to be the same as ISA device\n",
address);
goto err_nodev;
}

View file

@ -286,8 +286,9 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
data->fan_div[nr] = 3;
break;
default:
dev_err(&client->dev, "fan_div value %ld not "
"supported. Choose one of 1, 2, 4 or 8!\n", val);
dev_err(&client->dev,
"fan_div value %ld not supported. Choose one of 1, 2, 4 or 8!\n",
val);
mutex_unlock(&data->update_lock);
return -EINVAL;
}

View file

@ -1293,8 +1293,8 @@ static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info)
company = lm85_read_value(client, LM85_REG_COMPANY);
verstep = lm85_read_value(client, LM85_REG_VERSTEP);
dev_dbg(&adapter->dev, "Detecting device at 0x%02x with "
"COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
dev_dbg(&adapter->dev,
"Detecting device at 0x%02x with COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
address, company, verstep);
/* All supported chips have the version in common */

View file

@ -354,12 +354,12 @@ static const unsigned long lm93_vin_val_max[16] = {
static unsigned LM93_IN_FROM_REG(int nr, u8 reg)
{
const long uV_max = lm93_vin_val_max[nr] * 1000;
const long uV_min = lm93_vin_val_min[nr] * 1000;
const long uv_max = lm93_vin_val_max[nr] * 1000;
const long uv_min = lm93_vin_val_min[nr] * 1000;
const long slope = (uV_max - uV_min) /
const long slope = (uv_max - uv_min) /
(lm93_vin_reg_max[nr] - lm93_vin_reg_min[nr]);
const long intercept = uV_min - slope * lm93_vin_reg_min[nr];
const long intercept = uv_min - slope * lm93_vin_reg_min[nr];
return (slope * reg + intercept + 500) / 1000;
}
@ -371,20 +371,20 @@ static unsigned LM93_IN_FROM_REG(int nr, u8 reg)
static u8 LM93_IN_TO_REG(int nr, unsigned val)
{
/* range limit */
const long mV = clamp_val(val,
const long mv = clamp_val(val,
lm93_vin_val_min[nr], lm93_vin_val_max[nr]);
/* try not to lose too much precision here */
const long uV = mV * 1000;
const long uV_max = lm93_vin_val_max[nr] * 1000;
const long uV_min = lm93_vin_val_min[nr] * 1000;
const long uv = mv * 1000;
const long uv_max = lm93_vin_val_max[nr] * 1000;
const long uv_min = lm93_vin_val_min[nr] * 1000;
/* convert */
const long slope = (uV_max - uV_min) /
const long slope = (uv_max - uv_min) /
(lm93_vin_reg_max[nr] - lm93_vin_reg_min[nr]);
const long intercept = uV_min - slope * lm93_vin_reg_min[nr];
const long intercept = uv_min - slope * lm93_vin_reg_min[nr];
u8 result = ((uV - intercept + (slope/2)) / slope);
u8 result = ((uv - intercept + (slope/2)) / slope);
result = clamp_val(result,
lm93_vin_reg_min[nr], lm93_vin_reg_max[nr]);
return result;
@ -393,10 +393,10 @@ static u8 LM93_IN_TO_REG(int nr, unsigned val)
/* vid in mV, upper == 0 indicates low limit, otherwise upper limit */
static unsigned LM93_IN_REL_FROM_REG(u8 reg, int upper, int vid)
{
const long uV_offset = upper ? (((reg >> 4 & 0x0f) + 1) * 12500) :
const long uv_offset = upper ? (((reg >> 4 & 0x0f) + 1) * 12500) :
(((reg >> 0 & 0x0f) + 1) * -25000);
const long uV_vid = vid * 1000;
return (uV_vid + uV_offset + 5000) / 10000;
const long uv_vid = vid * 1000;
return (uv_vid + uv_offset + 5000) / 10000;
}
#define LM93_IN_MIN_FROM_REG(reg, vid) LM93_IN_REL_FROM_REG((reg), 0, (vid))
@ -409,13 +409,13 @@ static unsigned LM93_IN_REL_FROM_REG(u8 reg, int upper, int vid)
*/
static u8 LM93_IN_REL_TO_REG(unsigned val, int upper, int vid)
{
long uV_offset = vid * 1000 - val * 10000;
long uv_offset = vid * 1000 - val * 10000;
if (upper) {
uV_offset = clamp_val(uV_offset, 12500, 200000);
return (u8)((uV_offset / 12500 - 1) << 4);
uv_offset = clamp_val(uv_offset, 12500, 200000);
return (u8)((uv_offset / 12500 - 1) << 4);
} else {
uV_offset = clamp_val(uV_offset, -400000, -25000);
return (u8)((uV_offset / -25000 - 1) << 0);
uv_offset = clamp_val(uv_offset, -400000, -25000);
return (u8)((uv_offset / -25000 - 1) << 0);
}
}
@ -818,8 +818,9 @@ static u8 lm93_read_byte(struct i2c_client *client, u8 reg)
if (value >= 0) {
return value;
} else {
dev_warn(&client->dev, "lm93: read byte data failed, "
"address 0x%02x.\n", reg);
dev_warn(&client->dev,
"lm93: read byte data failed, address 0x%02x.\n",
reg);
mdelay(i + 3);
}
@ -838,8 +839,9 @@ static int lm93_write_byte(struct i2c_client *client, u8 reg, u8 value)
result = i2c_smbus_write_byte_data(client, reg, value);
if (result < 0)
dev_warn(&client->dev, "lm93: write byte data failed, "
"0x%02x at address 0x%02x.\n", value, reg);
dev_warn(&client->dev,
"lm93: write byte data failed, 0x%02x at address 0x%02x.\n",
value, reg);
return result;
}
@ -854,8 +856,9 @@ static u16 lm93_read_word(struct i2c_client *client, u8 reg)
if (value >= 0) {
return value;
} else {
dev_warn(&client->dev, "lm93: read word data failed, "
"address 0x%02x.\n", reg);
dev_warn(&client->dev,
"lm93: read word data failed, address 0x%02x.\n",
reg);
mdelay(i + 3);
}
@ -874,8 +877,9 @@ static int lm93_write_word(struct i2c_client *client, u8 reg, u16 value)
result = i2c_smbus_write_word_data(client, reg, value);
if (result < 0)
dev_warn(&client->dev, "lm93: write word data failed, "
"0x%04x at address 0x%02x.\n", value, reg);
dev_warn(&client->dev,
"lm93: write word data failed, 0x%04x at address 0x%02x.\n",
value, reg);
return result;
}
@ -898,8 +902,8 @@ static void lm93_read_block(struct i2c_client *client, u8 fbn, u8 *values)
if (result == lm93_block_read_cmds[fbn].len) {
break;
} else {
dev_warn(&client->dev, "lm93: block read data failed, "
"command 0x%02x.\n",
dev_warn(&client->dev,
"lm93: block read data failed, command 0x%02x.\n",
lm93_block_read_cmds[fbn].cmd);
mdelay(i + 3);
}
@ -2672,8 +2676,8 @@ static void lm93_init_client(struct i2c_client *client)
return;
}
dev_warn(&client->dev, "timed out waiting for sensor "
"chip to signal ready!\n");
dev_warn(&client->dev,
"timed out waiting for sensor chip to signal ready!\n");
}
/* Return 0 if detection is successful, -ENODEV otherwise */
@ -2733,12 +2737,12 @@ static int lm93_probe(struct i2c_client *client,
dev_dbg(&client->dev, "using SMBus block data transactions\n");
update = lm93_update_client_full;
} else if ((LM93_SMBUS_FUNC_MIN & func) == LM93_SMBUS_FUNC_MIN) {
dev_dbg(&client->dev, "disabled SMBus block data "
"transactions\n");
dev_dbg(&client->dev,
"disabled SMBus block data transactions\n");
update = lm93_update_client_min;
} else {
dev_dbg(&client->dev, "detect failed, "
"smbus byte and/or word data not supported!\n");
dev_dbg(&client->dev,
"detect failed, smbus byte and/or word data not supported!\n");
return -ENODEV;
}

769
drivers/hwmon/lm95234.c Normal file
View file

@ -0,0 +1,769 @@
/*
* Driver for Texas Instruments / National Semiconductor LM95234
*
* Copyright (c) 2013 Guenter Roeck <linux@roeck-us.net>
*
* Derived from lm95241.c
* Copyright (C) 2008, 2010 Davide Rizzo <elpa.rizzo@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#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>
#define DRVNAME "lm95234"
static const unsigned short normal_i2c[] = { 0x18, 0x4d, 0x4e, I2C_CLIENT_END };
/* LM95234 registers */
#define LM95234_REG_MAN_ID 0xFE
#define LM95234_REG_CHIP_ID 0xFF
#define LM95234_REG_STATUS 0x02
#define LM95234_REG_CONFIG 0x03
#define LM95234_REG_CONVRATE 0x04
#define LM95234_REG_STS_FAULT 0x07
#define LM95234_REG_STS_TCRIT1 0x08
#define LM95234_REG_STS_TCRIT2 0x09
#define LM95234_REG_TEMPH(x) ((x) + 0x10)
#define LM95234_REG_TEMPL(x) ((x) + 0x20)
#define LM95234_REG_UTEMPH(x) ((x) + 0x19) /* Remote only */
#define LM95234_REG_UTEMPL(x) ((x) + 0x29)
#define LM95234_REG_REM_MODEL 0x30
#define LM95234_REG_REM_MODEL_STS 0x38
#define LM95234_REG_OFFSET(x) ((x) + 0x31) /* Remote only */
#define LM95234_REG_TCRIT1(x) ((x) + 0x40)
#define LM95234_REG_TCRIT2(x) ((x) + 0x49) /* Remote channel 1,2 */
#define LM95234_REG_TCRIT_HYST 0x5a
#define NATSEMI_MAN_ID 0x01
#define LM95234_CHIP_ID 0x79
/* Client data (each client gets its own) */
struct lm95234_data {
struct device *hwmon_dev;
struct mutex update_lock;
unsigned long last_updated, interval; /* in jiffies */
bool valid; /* false until following fields are valid */
/* registers values */
int temp[5]; /* temperature (signed) */
u32 status; /* fault/alarm status */
u8 tcrit1[5]; /* critical temperature limit */
u8 tcrit2[2]; /* high temperature limit */
s8 toffset[4]; /* remote temperature offset */
u8 thyst; /* common hysteresis */
u8 sensor_type; /* temperature sensor type */
};
static int lm95234_read_temp(struct i2c_client *client, int index, int *t)
{
int val;
u16 temp = 0;
if (index) {
val = i2c_smbus_read_byte_data(client,
LM95234_REG_UTEMPH(index - 1));
if (val < 0)
return val;
temp = val << 8;
val = i2c_smbus_read_byte_data(client,
LM95234_REG_UTEMPL(index - 1));
if (val < 0)
return val;
temp |= val;
*t = temp;
}
/*
* Read signed temperature if unsigned temperature is 0,
* or if this is the local sensor.
*/
if (!temp) {
val = i2c_smbus_read_byte_data(client,
LM95234_REG_TEMPH(index));
if (val < 0)
return val;
temp = val << 8;
val = i2c_smbus_read_byte_data(client,
LM95234_REG_TEMPL(index));
if (val < 0)
return val;
temp |= val;
*t = (s16)temp;
}
return 0;
}
static u16 update_intervals[] = { 143, 364, 1000, 2500 };
/* Fill value cache. Must be called with update lock held. */
static int lm95234_fill_cache(struct i2c_client *client)
{
struct lm95234_data *data = i2c_get_clientdata(client);
int i, ret;
ret = i2c_smbus_read_byte_data(client, LM95234_REG_CONVRATE);
if (ret < 0)
return ret;
data->interval = msecs_to_jiffies(update_intervals[ret & 0x03]);
for (i = 0; i < ARRAY_SIZE(data->tcrit1); i++) {
ret = i2c_smbus_read_byte_data(client, LM95234_REG_TCRIT1(i));
if (ret < 0)
return ret;
data->tcrit1[i] = ret;
}
for (i = 0; i < ARRAY_SIZE(data->tcrit2); i++) {
ret = i2c_smbus_read_byte_data(client, LM95234_REG_TCRIT2(i));
if (ret < 0)
return ret;
data->tcrit2[i] = ret;
}
for (i = 0; i < ARRAY_SIZE(data->toffset); i++) {
ret = i2c_smbus_read_byte_data(client, LM95234_REG_OFFSET(i));
if (ret < 0)
return ret;
data->toffset[i] = ret;
}
ret = i2c_smbus_read_byte_data(client, LM95234_REG_TCRIT_HYST);
if (ret < 0)
return ret;
data->thyst = ret;
ret = i2c_smbus_read_byte_data(client, LM95234_REG_REM_MODEL);
if (ret < 0)
return ret;
data->sensor_type = ret;
return 0;
}
static int lm95234_update_device(struct i2c_client *client,
struct lm95234_data *data)
{
int ret;
mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + data->interval) ||
!data->valid) {
int i;
if (!data->valid) {
ret = lm95234_fill_cache(client);
if (ret < 0)
goto abort;
}
data->valid = false;
for (i = 0; i < ARRAY_SIZE(data->temp); i++) {
ret = lm95234_read_temp(client, i, &data->temp[i]);
if (ret < 0)
goto abort;
}
ret = i2c_smbus_read_byte_data(client, LM95234_REG_STS_FAULT);
if (ret < 0)
goto abort;
data->status = ret;
ret = i2c_smbus_read_byte_data(client, LM95234_REG_STS_TCRIT1);
if (ret < 0)
goto abort;
data->status |= ret << 8;
ret = i2c_smbus_read_byte_data(client, LM95234_REG_STS_TCRIT2);
if (ret < 0)
goto abort;
data->status |= ret << 16;
data->last_updated = jiffies;
data->valid = true;
}
ret = 0;
abort:
mutex_unlock(&data->update_lock);
return ret;
}
static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm95234_data *data = i2c_get_clientdata(client);
int index = to_sensor_dev_attr(attr)->index;
int ret = lm95234_update_device(client, data);
if (ret)
return ret;
return sprintf(buf, "%d\n",
DIV_ROUND_CLOSEST(data->temp[index] * 125, 32));
}
static ssize_t show_alarm(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm95234_data *data = i2c_get_clientdata(client);
u32 mask = to_sensor_dev_attr(attr)->index;
int ret = lm95234_update_device(client, data);
if (ret)
return ret;
return sprintf(buf, "%u", !!(data->status & mask));
}
static ssize_t show_type(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm95234_data *data = i2c_get_clientdata(client);
u8 mask = to_sensor_dev_attr(attr)->index;
int ret = lm95234_update_device(client, data);
if (ret)
return ret;
return sprintf(buf, data->sensor_type & mask ? "1\n" : "2\n");
}
static ssize_t set_type(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm95234_data *data = i2c_get_clientdata(client);
unsigned long val;
u8 mask = to_sensor_dev_attr(attr)->index;
int ret = lm95234_update_device(client, data);
if (ret)
return ret;
ret = kstrtoul(buf, 10, &val);
if (ret < 0)
return ret;
if (val != 1 && val != 2)
return -EINVAL;
mutex_lock(&data->update_lock);
if (val == 1)
data->sensor_type |= mask;
else
data->sensor_type &= ~mask;
data->valid = false;
i2c_smbus_write_byte_data(client, LM95234_REG_REM_MODEL,
data->sensor_type);
mutex_unlock(&data->update_lock);
return count;
}
static ssize_t show_tcrit2(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm95234_data *data = i2c_get_clientdata(client);
int index = to_sensor_dev_attr(attr)->index;
int ret = lm95234_update_device(client, data);
if (ret)
return ret;
return sprintf(buf, "%u", data->tcrit2[index] * 1000);
}
static ssize_t set_tcrit2(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm95234_data *data = i2c_get_clientdata(client);
int index = to_sensor_dev_attr(attr)->index;
long val;
int ret = lm95234_update_device(client, data);
if (ret)
return ret;
ret = kstrtol(buf, 10, &val);
if (ret < 0)
return ret;
val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, index ? 255 : 127);
mutex_lock(&data->update_lock);
data->tcrit2[index] = val;
i2c_smbus_write_byte_data(client, LM95234_REG_TCRIT2(index), val);
mutex_unlock(&data->update_lock);
return count;
}
static ssize_t show_tcrit2_hyst(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm95234_data *data = i2c_get_clientdata(client);
int index = to_sensor_dev_attr(attr)->index;
int ret = lm95234_update_device(client, data);
if (ret)
return ret;
/* Result can be negative, so be careful with unsigned operands */
return sprintf(buf, "%d",
((int)data->tcrit2[index] - (int)data->thyst) * 1000);
}
static ssize_t show_tcrit1(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm95234_data *data = i2c_get_clientdata(client);
int index = to_sensor_dev_attr(attr)->index;
return sprintf(buf, "%u", data->tcrit1[index] * 1000);
}
static ssize_t set_tcrit1(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm95234_data *data = i2c_get_clientdata(client);
int index = to_sensor_dev_attr(attr)->index;
long val;
int ret = lm95234_update_device(client, data);
if (ret)
return ret;
ret = kstrtol(buf, 10, &val);
if (ret < 0)
return ret;
val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 255);
mutex_lock(&data->update_lock);
data->tcrit1[index] = val;
i2c_smbus_write_byte_data(client, LM95234_REG_TCRIT1(index), val);
mutex_unlock(&data->update_lock);
return count;
}
static ssize_t show_tcrit1_hyst(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm95234_data *data = i2c_get_clientdata(client);
int index = to_sensor_dev_attr(attr)->index;
int ret = lm95234_update_device(client, data);
if (ret)
return ret;
/* Result can be negative, so be careful with unsigned operands */
return sprintf(buf, "%d",
((int)data->tcrit1[index] - (int)data->thyst) * 1000);
}
static ssize_t set_tcrit1_hyst(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm95234_data *data = i2c_get_clientdata(client);
int index = to_sensor_dev_attr(attr)->index;
long val;
int ret = lm95234_update_device(client, data);
if (ret)
return ret;
ret = kstrtol(buf, 10, &val);
if (ret < 0)
return ret;
val = DIV_ROUND_CLOSEST(val, 1000);
val = clamp_val((int)data->tcrit1[index] - val, 0, 31);
mutex_lock(&data->update_lock);
data->thyst = val;
i2c_smbus_write_byte_data(client, LM95234_REG_TCRIT_HYST, val);
mutex_unlock(&data->update_lock);
return count;
}
static ssize_t show_offset(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm95234_data *data = i2c_get_clientdata(client);
int index = to_sensor_dev_attr(attr)->index;
int ret = lm95234_update_device(client, data);
if (ret)
return ret;
return sprintf(buf, "%d", data->toffset[index] * 500);
}
static ssize_t set_offset(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm95234_data *data = i2c_get_clientdata(client);
int index = to_sensor_dev_attr(attr)->index;
long val;
int ret = lm95234_update_device(client, data);
if (ret)
return ret;
ret = kstrtol(buf, 10, &val);
if (ret < 0)
return ret;
/* Accuracy is 1/2 degrees C */
val = clamp_val(DIV_ROUND_CLOSEST(val, 500), -128, 127);
mutex_lock(&data->update_lock);
data->toffset[index] = val;
i2c_smbus_write_byte_data(client, LM95234_REG_OFFSET(index), val);
mutex_unlock(&data->update_lock);
return count;
}
static ssize_t show_interval(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm95234_data *data = i2c_get_clientdata(client);
int ret = lm95234_update_device(client, data);
if (ret)
return ret;
return sprintf(buf, "%lu\n",
DIV_ROUND_CLOSEST(data->interval * 1000, HZ));
}
static ssize_t set_interval(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm95234_data *data = i2c_get_clientdata(client);
unsigned long val;
u8 regval;
int ret = lm95234_update_device(client, data);
if (ret)
return ret;
ret = kstrtoul(buf, 10, &val);
if (ret < 0)
return ret;
for (regval = 0; regval < 3; regval++) {
if (val <= update_intervals[regval])
break;
}
mutex_lock(&data->update_lock);
data->interval = msecs_to_jiffies(update_intervals[regval]);
i2c_smbus_write_byte_data(client, LM95234_REG_CONVRATE, regval);
mutex_unlock(&data->update_lock);
return count;
}
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3);
static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp, NULL, 4);
static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL,
BIT(0) | BIT(1));
static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL,
BIT(2) | BIT(3));
static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_alarm, NULL,
BIT(4) | BIT(5));
static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_alarm, NULL,
BIT(6) | BIT(7));
static SENSOR_DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type, set_type,
BIT(1));
static SENSOR_DEVICE_ATTR(temp3_type, S_IWUSR | S_IRUGO, show_type, set_type,
BIT(2));
static SENSOR_DEVICE_ATTR(temp4_type, S_IWUSR | S_IRUGO, show_type, set_type,
BIT(3));
static SENSOR_DEVICE_ATTR(temp5_type, S_IWUSR | S_IRUGO, show_type, set_type,
BIT(4));
static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_tcrit1,
set_tcrit1, 0);
static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_tcrit2,
set_tcrit2, 0);
static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_tcrit2,
set_tcrit2, 1);
static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_tcrit1,
set_tcrit1, 3);
static SENSOR_DEVICE_ATTR(temp5_max, S_IWUSR | S_IRUGO, show_tcrit1,
set_tcrit1, 4);
static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_tcrit1_hyst,
set_tcrit1_hyst, 0);
static SENSOR_DEVICE_ATTR(temp2_max_hyst, S_IRUGO, show_tcrit2_hyst, NULL, 0);
static SENSOR_DEVICE_ATTR(temp3_max_hyst, S_IRUGO, show_tcrit2_hyst, NULL, 1);
static SENSOR_DEVICE_ATTR(temp4_max_hyst, S_IRUGO, show_tcrit1_hyst, NULL, 3);
static SENSOR_DEVICE_ATTR(temp5_max_hyst, S_IRUGO, show_tcrit1_hyst, NULL, 4);
static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL,
BIT(0 + 8));
static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL,
BIT(1 + 16));
static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL,
BIT(2 + 16));
static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_alarm, NULL,
BIT(3 + 8));
static SENSOR_DEVICE_ATTR(temp5_max_alarm, S_IRUGO, show_alarm, NULL,
BIT(4 + 8));
static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_tcrit1,
set_tcrit1, 1);
static SENSOR_DEVICE_ATTR(temp3_crit, S_IWUSR | S_IRUGO, show_tcrit1,
set_tcrit1, 2);
static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_tcrit1_hyst, NULL, 1);
static SENSOR_DEVICE_ATTR(temp3_crit_hyst, S_IRUGO, show_tcrit1_hyst, NULL, 2);
static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL,
BIT(1 + 8));
static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL,
BIT(2 + 8));
static SENSOR_DEVICE_ATTR(temp2_offset, S_IWUSR | S_IRUGO, show_offset,
set_offset, 0);
static SENSOR_DEVICE_ATTR(temp3_offset, S_IWUSR | S_IRUGO, show_offset,
set_offset, 1);
static SENSOR_DEVICE_ATTR(temp4_offset, S_IWUSR | S_IRUGO, show_offset,
set_offset, 2);
static SENSOR_DEVICE_ATTR(temp5_offset, S_IWUSR | S_IRUGO, show_offset,
set_offset, 3);
static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_interval,
set_interval);
static struct attribute *lm95234_attributes[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp2_input.dev_attr.attr,
&sensor_dev_attr_temp3_input.dev_attr.attr,
&sensor_dev_attr_temp4_input.dev_attr.attr,
&sensor_dev_attr_temp5_input.dev_attr.attr,
&sensor_dev_attr_temp2_fault.dev_attr.attr,
&sensor_dev_attr_temp3_fault.dev_attr.attr,
&sensor_dev_attr_temp4_fault.dev_attr.attr,
&sensor_dev_attr_temp5_fault.dev_attr.attr,
&sensor_dev_attr_temp2_type.dev_attr.attr,
&sensor_dev_attr_temp3_type.dev_attr.attr,
&sensor_dev_attr_temp4_type.dev_attr.attr,
&sensor_dev_attr_temp5_type.dev_attr.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr,
&sensor_dev_attr_temp2_max.dev_attr.attr,
&sensor_dev_attr_temp3_max.dev_attr.attr,
&sensor_dev_attr_temp4_max.dev_attr.attr,
&sensor_dev_attr_temp5_max.dev_attr.attr,
&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
&sensor_dev_attr_temp2_max_hyst.dev_attr.attr,
&sensor_dev_attr_temp3_max_hyst.dev_attr.attr,
&sensor_dev_attr_temp4_max_hyst.dev_attr.attr,
&sensor_dev_attr_temp5_max_hyst.dev_attr.attr,
&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp5_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp2_crit.dev_attr.attr,
&sensor_dev_attr_temp3_crit.dev_attr.attr,
&sensor_dev_attr_temp2_crit_hyst.dev_attr.attr,
&sensor_dev_attr_temp3_crit_hyst.dev_attr.attr,
&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp2_offset.dev_attr.attr,
&sensor_dev_attr_temp3_offset.dev_attr.attr,
&sensor_dev_attr_temp4_offset.dev_attr.attr,
&sensor_dev_attr_temp5_offset.dev_attr.attr,
&dev_attr_update_interval.attr,
NULL
};
static const struct attribute_group lm95234_group = {
.attrs = lm95234_attributes,
};
static int lm95234_detect(struct i2c_client *client,
struct i2c_board_info *info)
{
struct i2c_adapter *adapter = client->adapter;
int mfg_id, chip_id, val;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV;
mfg_id = i2c_smbus_read_byte_data(client, LM95234_REG_MAN_ID);
if (mfg_id != NATSEMI_MAN_ID)
return -ENODEV;
chip_id = i2c_smbus_read_byte_data(client, LM95234_REG_CHIP_ID);
if (chip_id != LM95234_CHIP_ID)
return -ENODEV;
val = i2c_smbus_read_byte_data(client, LM95234_REG_STATUS);
if (val & 0x30)
return -ENODEV;
val = i2c_smbus_read_byte_data(client, LM95234_REG_CONFIG);
if (val & 0xbc)
return -ENODEV;
val = i2c_smbus_read_byte_data(client, LM95234_REG_CONVRATE);
if (val & 0xfc)
return -ENODEV;
val = i2c_smbus_read_byte_data(client, LM95234_REG_REM_MODEL);
if (val & 0xe1)
return -ENODEV;
val = i2c_smbus_read_byte_data(client, LM95234_REG_REM_MODEL_STS);
if (val & 0xe1)
return -ENODEV;
strlcpy(info->type, "lm95234", I2C_NAME_SIZE);
return 0;
}
static int lm95234_init_client(struct i2c_client *client)
{
int val, model;
/* start conversion if necessary */
val = i2c_smbus_read_byte_data(client, LM95234_REG_CONFIG);
if (val < 0)
return val;
if (val & 0x40)
i2c_smbus_write_byte_data(client, LM95234_REG_CONFIG,
val & ~0x40);
/* If diode type status reports an error, try to fix it */
val = i2c_smbus_read_byte_data(client, LM95234_REG_REM_MODEL_STS);
if (val < 0)
return val;
model = i2c_smbus_read_byte_data(client, LM95234_REG_REM_MODEL);
if (model < 0)
return model;
if (model & val) {
dev_notice(&client->dev,
"Fixing remote diode type misconfiguration (0x%x)\n",
val);
i2c_smbus_write_byte_data(client, LM95234_REG_REM_MODEL,
model & ~val);
}
return 0;
}
static int lm95234_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
struct lm95234_data *data;
int err;
data = devm_kzalloc(dev, sizeof(struct lm95234_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
/* Initialize the LM95234 chip */
err = lm95234_init_client(client);
if (err < 0)
return err;
/* Register sysfs hooks */
err = sysfs_create_group(&dev->kobj, &lm95234_group);
if (err)
return err;
data->hwmon_dev = hwmon_device_register(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(&dev->kobj, &lm95234_group);
return err;
}
static int lm95234_remove(struct i2c_client *client)
{
struct lm95234_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm95234_group);
return 0;
}
/* Driver data (common to all clients) */
static const struct i2c_device_id lm95234_id[] = {
{ "lm95234", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm95234_id);
static struct i2c_driver lm95234_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = DRVNAME,
},
.probe = lm95234_probe,
.remove = lm95234_remove,
.id_table = lm95234_id,
.detect = lm95234_detect,
.address_list = normal_i2c,
};
module_i2c_driver(lm95234_driver);
MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
MODULE_DESCRIPTION("LM95234 sensor driver");
MODULE_LICENSE("GPL");

View file

@ -146,14 +146,14 @@ static ssize_t ltc4151_show_value(struct device *dev,
/*
* 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);
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);
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,

View file

@ -172,12 +172,12 @@ static ssize_t ltc4215_show_alarm(struct device *dev,
struct device_attribute *da,
char *buf)
{
struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(da);
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct ltc4215_data *data = ltc4215_update_device(dev);
const u8 reg = data->regs[attr->index];
const u32 mask = attr->nr;
const u8 reg = data->regs[LTC4215_STATUS];
const u32 mask = attr->index;
return snprintf(buf, PAGE_SIZE, "%u\n", (reg & mask) ? 1 : 0);
return snprintf(buf, PAGE_SIZE, "%u\n", !!(reg & mask));
}
/*
@ -186,39 +186,29 @@ static ssize_t ltc4215_show_alarm(struct device *dev,
* for each register.
*/
#define LTC4215_VOLTAGE(name, ltc4215_cmd_idx) \
static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
ltc4215_show_voltage, NULL, ltc4215_cmd_idx)
#define LTC4215_CURRENT(name) \
static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
ltc4215_show_current, NULL, 0);
#define LTC4215_POWER(name) \
static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
ltc4215_show_power, NULL, 0);
#define LTC4215_ALARM(name, mask, reg) \
static SENSOR_DEVICE_ATTR_2(name, S_IRUGO, \
ltc4215_show_alarm, NULL, (mask), reg)
/* Construct a sensor_device_attribute structure for each register */
/* Current */
LTC4215_CURRENT(curr1_input);
LTC4215_ALARM(curr1_max_alarm, (1 << 2), LTC4215_STATUS);
static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc4215_show_current, NULL, 0);
static SENSOR_DEVICE_ATTR(curr1_max_alarm, S_IRUGO, ltc4215_show_alarm, NULL,
1 << 2);
/* Power (virtual) */
LTC4215_POWER(power1_input);
static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, ltc4215_show_power, NULL, 0);
/* Input Voltage */
LTC4215_VOLTAGE(in1_input, LTC4215_ADIN);
LTC4215_ALARM(in1_max_alarm, (1 << 0), LTC4215_STATUS);
LTC4215_ALARM(in1_min_alarm, (1 << 1), LTC4215_STATUS);
static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ltc4215_show_voltage, NULL,
LTC4215_ADIN);
static SENSOR_DEVICE_ATTR(in1_max_alarm, S_IRUGO, ltc4215_show_alarm, NULL,
1 << 0);
static SENSOR_DEVICE_ATTR(in1_min_alarm, S_IRUGO, ltc4215_show_alarm, NULL,
1 << 1);
/* Output Voltage */
LTC4215_VOLTAGE(in2_input, LTC4215_SOURCE);
LTC4215_ALARM(in2_min_alarm, (1 << 3), LTC4215_STATUS);
static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ltc4215_show_voltage, NULL,
LTC4215_SOURCE);
static SENSOR_DEVICE_ATTR(in2_min_alarm, S_IRUGO, ltc4215_show_alarm, NULL,
1 << 3);
/*
* Finally, construct an array of pointers to members of the above objects,

View file

@ -319,80 +319,82 @@ static ssize_t ltc4245_show_gpio(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%u\n", val * 10);
}
/*
* These macros are used below in constructing device attribute objects
* for use with sysfs_create_group() to make a sysfs device file
* for each register.
*/
#define LTC4245_VOLTAGE(name, ltc4245_cmd_idx) \
static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
ltc4245_show_voltage, NULL, ltc4245_cmd_idx)
#define LTC4245_CURRENT(name, ltc4245_cmd_idx) \
static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
ltc4245_show_current, NULL, ltc4245_cmd_idx)
#define LTC4245_POWER(name, ltc4245_cmd_idx) \
static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
ltc4245_show_power, NULL, ltc4245_cmd_idx)
#define LTC4245_ALARM(name, mask, reg) \
static SENSOR_DEVICE_ATTR_2(name, S_IRUGO, \
ltc4245_show_alarm, NULL, (mask), reg)
#define LTC4245_GPIO_VOLTAGE(name, gpio_num) \
static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
ltc4245_show_gpio, NULL, gpio_num)
/* Construct a sensor_device_attribute structure for each register */
/* Input voltages */
LTC4245_VOLTAGE(in1_input, LTC4245_12VIN);
LTC4245_VOLTAGE(in2_input, LTC4245_5VIN);
LTC4245_VOLTAGE(in3_input, LTC4245_3VIN);
LTC4245_VOLTAGE(in4_input, LTC4245_VEEIN);
static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ltc4245_show_voltage, NULL,
LTC4245_12VIN);
static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ltc4245_show_voltage, NULL,
LTC4245_5VIN);
static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, ltc4245_show_voltage, NULL,
LTC4245_3VIN);
static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, ltc4245_show_voltage, NULL,
LTC4245_VEEIN);
/* Input undervoltage alarms */
LTC4245_ALARM(in1_min_alarm, (1 << 0), LTC4245_FAULT1);
LTC4245_ALARM(in2_min_alarm, (1 << 1), LTC4245_FAULT1);
LTC4245_ALARM(in3_min_alarm, (1 << 2), LTC4245_FAULT1);
LTC4245_ALARM(in4_min_alarm, (1 << 3), LTC4245_FAULT1);
static SENSOR_DEVICE_ATTR_2(in1_min_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
1 << 0, LTC4245_FAULT1);
static SENSOR_DEVICE_ATTR_2(in2_min_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
1 << 1, LTC4245_FAULT1);
static SENSOR_DEVICE_ATTR_2(in3_min_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
1 << 2, LTC4245_FAULT1);
static SENSOR_DEVICE_ATTR_2(in4_min_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
1 << 3, LTC4245_FAULT1);
/* Currents (via sense resistor) */
LTC4245_CURRENT(curr1_input, LTC4245_12VSENSE);
LTC4245_CURRENT(curr2_input, LTC4245_5VSENSE);
LTC4245_CURRENT(curr3_input, LTC4245_3VSENSE);
LTC4245_CURRENT(curr4_input, LTC4245_VEESENSE);
static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc4245_show_current, NULL,
LTC4245_12VSENSE);
static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, ltc4245_show_current, NULL,
LTC4245_5VSENSE);
static SENSOR_DEVICE_ATTR(curr3_input, S_IRUGO, ltc4245_show_current, NULL,
LTC4245_3VSENSE);
static SENSOR_DEVICE_ATTR(curr4_input, S_IRUGO, ltc4245_show_current, NULL,
LTC4245_VEESENSE);
/* Overcurrent alarms */
LTC4245_ALARM(curr1_max_alarm, (1 << 4), LTC4245_FAULT1);
LTC4245_ALARM(curr2_max_alarm, (1 << 5), LTC4245_FAULT1);
LTC4245_ALARM(curr3_max_alarm, (1 << 6), LTC4245_FAULT1);
LTC4245_ALARM(curr4_max_alarm, (1 << 7), LTC4245_FAULT1);
static SENSOR_DEVICE_ATTR_2(curr1_max_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
1 << 4, LTC4245_FAULT1);
static SENSOR_DEVICE_ATTR_2(curr2_max_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
1 << 5, LTC4245_FAULT1);
static SENSOR_DEVICE_ATTR_2(curr3_max_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
1 << 6, LTC4245_FAULT1);
static SENSOR_DEVICE_ATTR_2(curr4_max_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
1 << 7, LTC4245_FAULT1);
/* Output voltages */
LTC4245_VOLTAGE(in5_input, LTC4245_12VOUT);
LTC4245_VOLTAGE(in6_input, LTC4245_5VOUT);
LTC4245_VOLTAGE(in7_input, LTC4245_3VOUT);
LTC4245_VOLTAGE(in8_input, LTC4245_VEEOUT);
static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, ltc4245_show_voltage, NULL,
LTC4245_12VOUT);
static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, ltc4245_show_voltage, NULL,
LTC4245_5VOUT);
static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, ltc4245_show_voltage, NULL,
LTC4245_3VOUT);
static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, ltc4245_show_voltage, NULL,
LTC4245_VEEOUT);
/* Power Bad alarms */
LTC4245_ALARM(in5_min_alarm, (1 << 0), LTC4245_FAULT2);
LTC4245_ALARM(in6_min_alarm, (1 << 1), LTC4245_FAULT2);
LTC4245_ALARM(in7_min_alarm, (1 << 2), LTC4245_FAULT2);
LTC4245_ALARM(in8_min_alarm, (1 << 3), LTC4245_FAULT2);
static SENSOR_DEVICE_ATTR_2(in5_min_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
1 << 0, LTC4245_FAULT2);
static SENSOR_DEVICE_ATTR_2(in6_min_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
1 << 1, LTC4245_FAULT2);
static SENSOR_DEVICE_ATTR_2(in7_min_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
1 << 2, LTC4245_FAULT2);
static SENSOR_DEVICE_ATTR_2(in8_min_alarm, S_IRUGO, ltc4245_show_alarm, NULL,
1 << 3, LTC4245_FAULT2);
/* GPIO voltages */
LTC4245_GPIO_VOLTAGE(in9_input, 0);
LTC4245_GPIO_VOLTAGE(in10_input, 1);
LTC4245_GPIO_VOLTAGE(in11_input, 2);
static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, ltc4245_show_gpio, NULL, 0);
static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, ltc4245_show_gpio, NULL, 1);
static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, ltc4245_show_gpio, NULL, 2);
/* Power Consumption (virtual) */
LTC4245_POWER(power1_input, LTC4245_12VSENSE);
LTC4245_POWER(power2_input, LTC4245_5VSENSE);
LTC4245_POWER(power3_input, LTC4245_3VSENSE);
LTC4245_POWER(power4_input, LTC4245_VEESENSE);
static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, ltc4245_show_power, NULL,
LTC4245_12VSENSE);
static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, ltc4245_show_power, NULL,
LTC4245_5VSENSE);
static SENSOR_DEVICE_ATTR(power3_input, S_IRUGO, ltc4245_show_power, NULL,
LTC4245_3VSENSE);
static SENSOR_DEVICE_ATTR(power4_input, S_IRUGO, ltc4245_show_power, NULL,
LTC4245_VEESENSE);
/*
* Finally, construct an array of pointers to members of the above objects,

View file

@ -164,25 +164,13 @@ static ssize_t ltc4261_show_bool(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%d\n", fault ? 1 : 0);
}
/*
* These macros are used below in constructing device attribute objects
* for use with sysfs_create_group() to make a sysfs device file
* for each register.
*/
#define LTC4261_VALUE(name, ltc4261_cmd_idx) \
static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
ltc4261_show_value, NULL, ltc4261_cmd_idx)
#define LTC4261_BOOL(name, mask) \
static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
ltc4261_show_bool, NULL, (mask))
/*
* Input voltages.
*/
LTC4261_VALUE(in1_input, LTC4261_ADIN_H);
LTC4261_VALUE(in2_input, LTC4261_ADIN2_H);
static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ltc4261_show_value, NULL,
LTC4261_ADIN_H);
static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ltc4261_show_value, NULL,
LTC4261_ADIN2_H);
/*
* Voltage alarms. The chip has only one set of voltage alarm status bits,
@ -192,16 +180,22 @@ LTC4261_VALUE(in2_input, LTC4261_ADIN2_H);
* To ensure that the alarm condition is reported to the user, report it
* with both voltage sensors.
*/
LTC4261_BOOL(in1_min_alarm, FAULT_UV);
LTC4261_BOOL(in1_max_alarm, FAULT_OV);
LTC4261_BOOL(in2_min_alarm, FAULT_UV);
LTC4261_BOOL(in2_max_alarm, FAULT_OV);
static SENSOR_DEVICE_ATTR(in1_min_alarm, S_IRUGO, ltc4261_show_bool, NULL,
FAULT_UV);
static SENSOR_DEVICE_ATTR(in1_max_alarm, S_IRUGO, ltc4261_show_bool, NULL,
FAULT_OV);
static SENSOR_DEVICE_ATTR(in2_min_alarm, S_IRUGO, ltc4261_show_bool, NULL,
FAULT_UV);
static SENSOR_DEVICE_ATTR(in2_max_alarm, S_IRUGO, ltc4261_show_bool, NULL,
FAULT_OV);
/* Currents (via sense resistor) */
LTC4261_VALUE(curr1_input, LTC4261_SENSE_H);
static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc4261_show_value, NULL,
LTC4261_SENSE_H);
/* Overcurrent alarm */
LTC4261_BOOL(curr1_max_alarm, FAULT_OC);
static SENSOR_DEVICE_ATTR(curr1_max_alarm, S_IRUGO, ltc4261_show_bool, NULL,
FAULT_OC);
static struct attribute *ltc4261_attributes[] = {
&sensor_dev_attr_in1_input.dev_attr.attr,

View file

@ -399,82 +399,95 @@ static SENSOR_DEVICE_ATTR(temp6_fault, S_IRUGO, show_alarm, NULL, 5);
static SENSOR_DEVICE_ATTR(temp7_fault, S_IRUGO, show_alarm, NULL, 6);
static SENSOR_DEVICE_ATTR(temp8_fault, S_IRUGO, show_alarm, NULL, 7);
static struct attribute *max6697_attributes[8][7] = {
{
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr,
&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp1_crit.dev_attr.attr,
&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
NULL
}, {
&sensor_dev_attr_temp2_input.dev_attr.attr,
&sensor_dev_attr_temp2_max.dev_attr.attr,
&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp2_crit.dev_attr.attr,
&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp2_fault.dev_attr.attr,
NULL
}, {
&sensor_dev_attr_temp3_input.dev_attr.attr,
&sensor_dev_attr_temp3_max.dev_attr.attr,
&sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp3_crit.dev_attr.attr,
&sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp3_fault.dev_attr.attr,
NULL
}, {
&sensor_dev_attr_temp4_input.dev_attr.attr,
&sensor_dev_attr_temp4_max.dev_attr.attr,
&sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp4_crit.dev_attr.attr,
&sensor_dev_attr_temp4_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp4_fault.dev_attr.attr,
NULL
}, {
&sensor_dev_attr_temp5_input.dev_attr.attr,
&sensor_dev_attr_temp5_max.dev_attr.attr,
&sensor_dev_attr_temp5_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp5_crit.dev_attr.attr,
&sensor_dev_attr_temp5_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp5_fault.dev_attr.attr,
NULL
}, {
&sensor_dev_attr_temp6_input.dev_attr.attr,
&sensor_dev_attr_temp6_max.dev_attr.attr,
&sensor_dev_attr_temp6_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp6_crit.dev_attr.attr,
&sensor_dev_attr_temp6_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp6_fault.dev_attr.attr,
NULL
}, {
&sensor_dev_attr_temp7_input.dev_attr.attr,
&sensor_dev_attr_temp7_max.dev_attr.attr,
&sensor_dev_attr_temp7_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp7_crit.dev_attr.attr,
&sensor_dev_attr_temp7_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp7_fault.dev_attr.attr,
NULL
}, {
&sensor_dev_attr_temp8_input.dev_attr.attr,
&sensor_dev_attr_temp8_max.dev_attr.attr,
&sensor_dev_attr_temp8_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp8_crit.dev_attr.attr,
&sensor_dev_attr_temp8_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp8_fault.dev_attr.attr,
NULL
}
static DEVICE_ATTR(dummy, 0, NULL, NULL);
static umode_t max6697_is_visible(struct kobject *kobj, struct attribute *attr,
int index)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct i2c_client *client = to_i2c_client(dev);
struct max6697_data *data = i2c_get_clientdata(client);
const struct max6697_chip_data *chip = data->chip;
int channel = index / 6; /* channel number */
int nr = index % 6; /* attribute index within channel */
if (channel >= chip->channels)
return 0;
if ((nr == 3 || nr == 4) && !(chip->have_crit & (1 << channel)))
return 0;
if (nr == 5 && !(chip->have_fault & (1 << channel)))
return 0;
return attr->mode;
}
/*
* max6697_is_visible uses the index into the following array to determine
* if attributes should be created or not. Any change in order or content
* must be matched in max6697_is_visible.
*/
static struct attribute *max6697_attributes[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr,
&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp1_crit.dev_attr.attr,
&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
&dev_attr_dummy.attr,
&sensor_dev_attr_temp2_input.dev_attr.attr,
&sensor_dev_attr_temp2_max.dev_attr.attr,
&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp2_crit.dev_attr.attr,
&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp2_fault.dev_attr.attr,
&sensor_dev_attr_temp3_input.dev_attr.attr,
&sensor_dev_attr_temp3_max.dev_attr.attr,
&sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp3_crit.dev_attr.attr,
&sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp3_fault.dev_attr.attr,
&sensor_dev_attr_temp4_input.dev_attr.attr,
&sensor_dev_attr_temp4_max.dev_attr.attr,
&sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp4_crit.dev_attr.attr,
&sensor_dev_attr_temp4_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp4_fault.dev_attr.attr,
&sensor_dev_attr_temp5_input.dev_attr.attr,
&sensor_dev_attr_temp5_max.dev_attr.attr,
&sensor_dev_attr_temp5_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp5_crit.dev_attr.attr,
&sensor_dev_attr_temp5_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp5_fault.dev_attr.attr,
&sensor_dev_attr_temp6_input.dev_attr.attr,
&sensor_dev_attr_temp6_max.dev_attr.attr,
&sensor_dev_attr_temp6_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp6_crit.dev_attr.attr,
&sensor_dev_attr_temp6_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp6_fault.dev_attr.attr,
&sensor_dev_attr_temp7_input.dev_attr.attr,
&sensor_dev_attr_temp7_max.dev_attr.attr,
&sensor_dev_attr_temp7_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp7_crit.dev_attr.attr,
&sensor_dev_attr_temp7_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp7_fault.dev_attr.attr,
&sensor_dev_attr_temp8_input.dev_attr.attr,
&sensor_dev_attr_temp8_max.dev_attr.attr,
&sensor_dev_attr_temp8_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp8_crit.dev_attr.attr,
&sensor_dev_attr_temp8_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp8_fault.dev_attr.attr,
NULL
};
static const struct attribute_group max6697_group[8] = {
{ .attrs = max6697_attributes[0] },
{ .attrs = max6697_attributes[1] },
{ .attrs = max6697_attributes[2] },
{ .attrs = max6697_attributes[3] },
{ .attrs = max6697_attributes[4] },
{ .attrs = max6697_attributes[5] },
{ .attrs = max6697_attributes[6] },
{ .attrs = max6697_attributes[7] },
static const struct attribute_group max6697_group = {
.attrs = max6697_attributes, .is_visible = max6697_is_visible,
};
static void max6697_get_config_of(struct device_node *node,
@ -606,21 +619,13 @@ done:
return 0;
}
static void max6697_remove_files(struct i2c_client *client)
{
int i;
for (i = 0; i < ARRAY_SIZE(max6697_group); i++)
sysfs_remove_group(&client->dev.kobj, &max6697_group[i]);
}
static int max6697_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct i2c_adapter *adapter = client->adapter;
struct device *dev = &client->dev;
struct max6697_data *data;
int i, err;
int err;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV;
@ -639,37 +644,9 @@ static int max6697_probe(struct i2c_client *client,
if (err)
return err;
for (i = 0; i < data->chip->channels; i++) {
err = sysfs_create_file(&dev->kobj,
max6697_attributes[i][0]);
if (err)
goto error;
err = sysfs_create_file(&dev->kobj,
max6697_attributes[i][1]);
if (err)
goto error;
err = sysfs_create_file(&dev->kobj,
max6697_attributes[i][2]);
if (err)
goto error;
if (data->chip->have_crit & (1 << i)) {
err = sysfs_create_file(&dev->kobj,
max6697_attributes[i][3]);
if (err)
goto error;
err = sysfs_create_file(&dev->kobj,
max6697_attributes[i][4]);
if (err)
goto error;
}
if (data->chip->have_fault & (1 << i)) {
err = sysfs_create_file(&dev->kobj,
max6697_attributes[i][5]);
if (err)
goto error;
}
}
err = sysfs_create_group(&client->dev.kobj, &max6697_group);
if (err)
return err;
data->hwmon_dev = hwmon_device_register(dev);
if (IS_ERR(data->hwmon_dev)) {
@ -680,7 +657,7 @@ static int max6697_probe(struct i2c_client *client,
return 0;
error:
max6697_remove_files(client);
sysfs_remove_group(&client->dev.kobj, &max6697_group);
return err;
}
@ -689,7 +666,7 @@ static int max6697_remove(struct i2c_client *client)
struct max6697_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
max6697_remove_files(client);
sysfs_remove_group(&client->dev.kobj, &max6697_group);
return 0;
}

View file

@ -273,18 +273,7 @@ static struct platform_driver mc13783_adc_driver = {
.id_table = mc13783_adc_idtable,
};
static int __init mc13783_adc_init(void)
{
return platform_driver_probe(&mc13783_adc_driver, mc13783_adc_probe);
}
static void __exit mc13783_adc_exit(void)
{
platform_driver_unregister(&mc13783_adc_driver);
}
module_init(mc13783_adc_init);
module_exit(mc13783_adc_exit);
module_platform_driver_probe(mc13783_adc_driver, mc13783_adc_probe);
MODULE_DESCRIPTION("MC13783 ADC driver");
MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>");

4191
drivers/hwmon/nct6775.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -26,17 +26,33 @@
#include <linux/math64.h>
#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_data/ntc_thermistor.h>
#include <linux/iio/iio.h>
#include <linux/iio/machine.h>
#include <linux/iio/driver.h>
#include <linux/iio/consumer.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
struct ntc_compensation {
int temp_C;
int temp_c;
unsigned int ohm;
};
static const struct platform_device_id ntc_thermistor_id[] = {
{ "ncp15wb473", TYPE_NCPXXWB473 },
{ "ncp18wb473", TYPE_NCPXXWB473 },
{ "ncp21wb473", TYPE_NCPXXWB473 },
{ "ncp03wb473", TYPE_NCPXXWB473 },
{ "ncp15wl333", TYPE_NCPXXWL333 },
{ },
};
/*
* A compensation table should be sorted by the values of .ohm
* in descending order.
@ -44,76 +60,76 @@ struct ntc_compensation {
* Thermistors Datasheet
*/
static const struct ntc_compensation ncpXXwb473[] = {
{ .temp_C = -40, .ohm = 1747920 },
{ .temp_C = -35, .ohm = 1245428 },
{ .temp_C = -30, .ohm = 898485 },
{ .temp_C = -25, .ohm = 655802 },
{ .temp_C = -20, .ohm = 483954 },
{ .temp_C = -15, .ohm = 360850 },
{ .temp_C = -10, .ohm = 271697 },
{ .temp_C = -5, .ohm = 206463 },
{ .temp_C = 0, .ohm = 158214 },
{ .temp_C = 5, .ohm = 122259 },
{ .temp_C = 10, .ohm = 95227 },
{ .temp_C = 15, .ohm = 74730 },
{ .temp_C = 20, .ohm = 59065 },
{ .temp_C = 25, .ohm = 47000 },
{ .temp_C = 30, .ohm = 37643 },
{ .temp_C = 35, .ohm = 30334 },
{ .temp_C = 40, .ohm = 24591 },
{ .temp_C = 45, .ohm = 20048 },
{ .temp_C = 50, .ohm = 16433 },
{ .temp_C = 55, .ohm = 13539 },
{ .temp_C = 60, .ohm = 11209 },
{ .temp_C = 65, .ohm = 9328 },
{ .temp_C = 70, .ohm = 7798 },
{ .temp_C = 75, .ohm = 6544 },
{ .temp_C = 80, .ohm = 5518 },
{ .temp_C = 85, .ohm = 4674 },
{ .temp_C = 90, .ohm = 3972 },
{ .temp_C = 95, .ohm = 3388 },
{ .temp_C = 100, .ohm = 2902 },
{ .temp_C = 105, .ohm = 2494 },
{ .temp_C = 110, .ohm = 2150 },
{ .temp_C = 115, .ohm = 1860 },
{ .temp_C = 120, .ohm = 1615 },
{ .temp_C = 125, .ohm = 1406 },
{ .temp_c = -40, .ohm = 1747920 },
{ .temp_c = -35, .ohm = 1245428 },
{ .temp_c = -30, .ohm = 898485 },
{ .temp_c = -25, .ohm = 655802 },
{ .temp_c = -20, .ohm = 483954 },
{ .temp_c = -15, .ohm = 360850 },
{ .temp_c = -10, .ohm = 271697 },
{ .temp_c = -5, .ohm = 206463 },
{ .temp_c = 0, .ohm = 158214 },
{ .temp_c = 5, .ohm = 122259 },
{ .temp_c = 10, .ohm = 95227 },
{ .temp_c = 15, .ohm = 74730 },
{ .temp_c = 20, .ohm = 59065 },
{ .temp_c = 25, .ohm = 47000 },
{ .temp_c = 30, .ohm = 37643 },
{ .temp_c = 35, .ohm = 30334 },
{ .temp_c = 40, .ohm = 24591 },
{ .temp_c = 45, .ohm = 20048 },
{ .temp_c = 50, .ohm = 16433 },
{ .temp_c = 55, .ohm = 13539 },
{ .temp_c = 60, .ohm = 11209 },
{ .temp_c = 65, .ohm = 9328 },
{ .temp_c = 70, .ohm = 7798 },
{ .temp_c = 75, .ohm = 6544 },
{ .temp_c = 80, .ohm = 5518 },
{ .temp_c = 85, .ohm = 4674 },
{ .temp_c = 90, .ohm = 3972 },
{ .temp_c = 95, .ohm = 3388 },
{ .temp_c = 100, .ohm = 2902 },
{ .temp_c = 105, .ohm = 2494 },
{ .temp_c = 110, .ohm = 2150 },
{ .temp_c = 115, .ohm = 1860 },
{ .temp_c = 120, .ohm = 1615 },
{ .temp_c = 125, .ohm = 1406 },
};
static const struct ntc_compensation ncpXXwl333[] = {
{ .temp_C = -40, .ohm = 1610154 },
{ .temp_C = -35, .ohm = 1130850 },
{ .temp_C = -30, .ohm = 802609 },
{ .temp_C = -25, .ohm = 575385 },
{ .temp_C = -20, .ohm = 416464 },
{ .temp_C = -15, .ohm = 304219 },
{ .temp_C = -10, .ohm = 224193 },
{ .temp_C = -5, .ohm = 166623 },
{ .temp_C = 0, .ohm = 124850 },
{ .temp_C = 5, .ohm = 94287 },
{ .temp_C = 10, .ohm = 71747 },
{ .temp_C = 15, .ohm = 54996 },
{ .temp_C = 20, .ohm = 42455 },
{ .temp_C = 25, .ohm = 33000 },
{ .temp_C = 30, .ohm = 25822 },
{ .temp_C = 35, .ohm = 20335 },
{ .temp_C = 40, .ohm = 16115 },
{ .temp_C = 45, .ohm = 12849 },
{ .temp_C = 50, .ohm = 10306 },
{ .temp_C = 55, .ohm = 8314 },
{ .temp_C = 60, .ohm = 6746 },
{ .temp_C = 65, .ohm = 5503 },
{ .temp_C = 70, .ohm = 4513 },
{ .temp_C = 75, .ohm = 3721 },
{ .temp_C = 80, .ohm = 3084 },
{ .temp_C = 85, .ohm = 2569 },
{ .temp_C = 90, .ohm = 2151 },
{ .temp_C = 95, .ohm = 1809 },
{ .temp_C = 100, .ohm = 1529 },
{ .temp_C = 105, .ohm = 1299 },
{ .temp_C = 110, .ohm = 1108 },
{ .temp_C = 115, .ohm = 949 },
{ .temp_C = 120, .ohm = 817 },
{ .temp_C = 125, .ohm = 707 },
{ .temp_c = -40, .ohm = 1610154 },
{ .temp_c = -35, .ohm = 1130850 },
{ .temp_c = -30, .ohm = 802609 },
{ .temp_c = -25, .ohm = 575385 },
{ .temp_c = -20, .ohm = 416464 },
{ .temp_c = -15, .ohm = 304219 },
{ .temp_c = -10, .ohm = 224193 },
{ .temp_c = -5, .ohm = 166623 },
{ .temp_c = 0, .ohm = 124850 },
{ .temp_c = 5, .ohm = 94287 },
{ .temp_c = 10, .ohm = 71747 },
{ .temp_c = 15, .ohm = 54996 },
{ .temp_c = 20, .ohm = 42455 },
{ .temp_c = 25, .ohm = 33000 },
{ .temp_c = 30, .ohm = 25822 },
{ .temp_c = 35, .ohm = 20335 },
{ .temp_c = 40, .ohm = 16115 },
{ .temp_c = 45, .ohm = 12849 },
{ .temp_c = 50, .ohm = 10306 },
{ .temp_c = 55, .ohm = 8314 },
{ .temp_c = 60, .ohm = 6746 },
{ .temp_c = 65, .ohm = 5503 },
{ .temp_c = 70, .ohm = 4513 },
{ .temp_c = 75, .ohm = 3721 },
{ .temp_c = 80, .ohm = 3084 },
{ .temp_c = 85, .ohm = 2569 },
{ .temp_c = 90, .ohm = 2151 },
{ .temp_c = 95, .ohm = 1809 },
{ .temp_c = 100, .ohm = 1529 },
{ .temp_c = 105, .ohm = 1299 },
{ .temp_c = 110, .ohm = 1108 },
{ .temp_c = 115, .ohm = 949 },
{ .temp_c = 120, .ohm = 817 },
{ .temp_c = 125, .ohm = 707 },
};
struct ntc_data {
@ -125,6 +141,92 @@ struct ntc_data {
char name[PLATFORM_NAME_SIZE];
};
#ifdef CONFIG_OF
static int ntc_adc_iio_read(struct ntc_thermistor_platform_data *pdata)
{
struct iio_channel *channel = pdata->chan;
unsigned int result;
int val, ret;
ret = iio_read_channel_raw(channel, &val);
if (ret < 0) {
pr_err("read channel() error: %d\n", ret);
return ret;
}
/* unit: mV */
result = pdata->pullup_uv * val;
result >>= 12;
return result;
}
static const struct of_device_id ntc_match[] = {
{ .compatible = "ntc,ncp15wb473",
.data = &ntc_thermistor_id[TYPE_NCPXXWB473] },
{ .compatible = "ntc,ncp18wb473",
.data = &ntc_thermistor_id[TYPE_NCPXXWB473] },
{ .compatible = "ntc,ncp21wb473",
.data = &ntc_thermistor_id[TYPE_NCPXXWB473] },
{ .compatible = "ntc,ncp03wb473",
.data = &ntc_thermistor_id[TYPE_NCPXXWB473] },
{ .compatible = "ntc,ncp15wl333",
.data = &ntc_thermistor_id[TYPE_NCPXXWL333] },
{ },
};
MODULE_DEVICE_TABLE(of, ntc_match);
static struct ntc_thermistor_platform_data *
ntc_thermistor_parse_dt(struct platform_device *pdev)
{
struct iio_channel *chan;
struct device_node *np = pdev->dev.of_node;
struct ntc_thermistor_platform_data *pdata;
if (!np)
return NULL;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return ERR_PTR(-ENOMEM);
chan = iio_channel_get(&pdev->dev, NULL);
if (IS_ERR(chan))
return ERR_CAST(chan);
if (of_property_read_u32(np, "pullup-uv", &pdata->pullup_uv))
return ERR_PTR(-ENODEV);
if (of_property_read_u32(np, "pullup-ohm", &pdata->pullup_ohm))
return ERR_PTR(-ENODEV);
if (of_property_read_u32(np, "pulldown-ohm", &pdata->pulldown_ohm))
return ERR_PTR(-ENODEV);
if (of_find_property(np, "connected-positive", NULL))
pdata->connect = NTC_CONNECTED_POSITIVE;
else /* status change should be possible if not always on. */
pdata->connect = NTC_CONNECTED_GROUND;
pdata->chan = chan;
pdata->read_uv = ntc_adc_iio_read;
return pdata;
}
static void ntc_iio_channel_release(struct ntc_thermistor_platform_data *pdata)
{
if (pdata->chan)
iio_channel_release(pdata->chan);
}
#else
static struct ntc_thermistor_platform_data *
ntc_thermistor_parse_dt(struct platform_device *pdev)
{
return NULL;
}
static void ntc_iio_channel_release(struct ntc_thermistor_platform_data *pdata)
{ }
#endif
static inline u64 div64_u64_safe(u64 dividend, u64 divisor)
{
if (divisor == 0 && dividend == 0)
@ -134,37 +236,37 @@ static inline u64 div64_u64_safe(u64 dividend, u64 divisor)
return div64_u64(dividend, divisor);
}
static int get_ohm_of_thermistor(struct ntc_data *data, unsigned int uV)
static int get_ohm_of_thermistor(struct ntc_data *data, unsigned int uv)
{
struct ntc_thermistor_platform_data *pdata = data->pdata;
u64 mV = uV / 1000;
u64 pmV = pdata->pullup_uV / 1000;
u64 N, puO, pdO;
puO = pdata->pullup_ohm;
pdO = pdata->pulldown_ohm;
u64 mv = uv / 1000;
u64 pmv = pdata->pullup_uv / 1000;
u64 n, puo, pdo;
puo = pdata->pullup_ohm;
pdo = pdata->pulldown_ohm;
if (mV == 0) {
if (mv == 0) {
if (pdata->connect == NTC_CONNECTED_POSITIVE)
return INT_MAX;
return 0;
}
if (mV >= pmV)
if (mv >= pmv)
return (pdata->connect == NTC_CONNECTED_POSITIVE) ?
0 : INT_MAX;
if (pdata->connect == NTC_CONNECTED_POSITIVE && puO == 0)
N = div64_u64_safe(pdO * (pmV - mV), mV);
else if (pdata->connect == NTC_CONNECTED_GROUND && pdO == 0)
N = div64_u64_safe(puO * mV, pmV - mV);
if (pdata->connect == NTC_CONNECTED_POSITIVE && puo == 0)
n = div64_u64_safe(pdo * (pmv - mv), mv);
else if (pdata->connect == NTC_CONNECTED_GROUND && pdo == 0)
n = div64_u64_safe(puo * mv, pmv - mv);
else if (pdata->connect == NTC_CONNECTED_POSITIVE)
N = div64_u64_safe(pdO * puO * (pmV - mV),
puO * mV - pdO * (pmV - mV));
n = div64_u64_safe(pdo * puo * (pmv - mv),
puo * mv - pdo * (pmv - mv));
else
N = div64_u64_safe(pdO * puO * mV, pdO * (pmV - mV) - puO * mV);
n = div64_u64_safe(pdo * puo * mv, pdo * (pmv - mv) - puo * mv);
if (N > INT_MAX)
N = INT_MAX;
return N;
if (n > INT_MAX)
n = INT_MAX;
return n;
}
static void lookup_comp(struct ntc_data *data, unsigned int ohm,
@ -233,7 +335,7 @@ static void lookup_comp(struct ntc_data *data, unsigned int ohm,
*i_high = end - 1;
}
static int get_temp_mC(struct ntc_data *data, unsigned int ohm)
static int get_temp_mc(struct ntc_data *data, unsigned int ohm)
{
int low, high;
int temp;
@ -241,10 +343,10 @@ static int get_temp_mC(struct ntc_data *data, unsigned int ohm)
lookup_comp(data, ohm, &low, &high);
if (low == high) {
/* Unable to use linear approximation */
temp = data->comp[low].temp_C * 1000;
temp = data->comp[low].temp_c * 1000;
} else {
temp = data->comp[low].temp_C * 1000 +
((data->comp[high].temp_C - data->comp[low].temp_C) *
temp = data->comp[low].temp_c * 1000 +
((data->comp[high].temp_c - data->comp[low].temp_c) *
1000 * ((int)ohm - (int)data->comp[low].ohm)) /
((int)data->comp[high].ohm - (int)data->comp[low].ohm);
}
@ -253,16 +355,16 @@ static int get_temp_mC(struct ntc_data *data, unsigned int ohm)
static int ntc_thermistor_get_ohm(struct ntc_data *data)
{
int read_uV;
int read_uv;
if (data->pdata->read_ohm)
return data->pdata->read_ohm();
if (data->pdata->read_uV) {
read_uV = data->pdata->read_uV();
if (read_uV < 0)
return read_uV;
return get_ohm_of_thermistor(data, read_uV);
if (data->pdata->read_uv) {
read_uv = data->pdata->read_uv(data->pdata);
if (read_uv < 0)
return read_uv;
return get_ohm_of_thermistor(data, read_uv);
}
return -EINVAL;
}
@ -291,7 +393,7 @@ static ssize_t ntc_show_temp(struct device *dev,
if (ohm < 0)
return ohm;
return sprintf(buf, "%d\n", get_temp_mC(data, ohm));
return sprintf(buf, "%d\n", get_temp_mc(data, ohm));
}
static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO, ntc_show_type, NULL, 0);
@ -311,9 +413,18 @@ static const struct attribute_group ntc_attr_group = {
static int ntc_thermistor_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id =
of_match_device(of_match_ptr(ntc_match), &pdev->dev);
const struct platform_device_id *pdev_id;
struct ntc_thermistor_platform_data *pdata;
struct ntc_data *data;
struct ntc_thermistor_platform_data *pdata = pdev->dev.platform_data;
int ret = 0;
int ret;
pdata = ntc_thermistor_parse_dt(pdev);
if (IS_ERR(pdata))
return PTR_ERR(pdata);
else if (pdata == NULL)
pdata = pdev->dev.platform_data;
if (!pdata) {
dev_err(&pdev->dev, "No platform init data supplied.\n");
@ -321,19 +432,19 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
}
/* Either one of the two is required. */
if (!pdata->read_uV && !pdata->read_ohm) {
if (!pdata->read_uv && !pdata->read_ohm) {
dev_err(&pdev->dev,
"Both read_uV and read_ohm missing. Need either one of the two.\n");
"Both read_uv and read_ohm missing. Need either one of the two.\n");
return -EINVAL;
}
if (pdata->read_uV && pdata->read_ohm) {
if (pdata->read_uv && pdata->read_ohm) {
dev_warn(&pdev->dev,
"Only one of read_uV and read_ohm is needed; ignoring read_uV.\n");
pdata->read_uV = NULL;
"Only one of read_uv and read_ohm is needed; ignoring read_uv.\n");
pdata->read_uv = NULL;
}
if (pdata->read_uV && (pdata->pullup_uV == 0 ||
if (pdata->read_uv && (pdata->pullup_uv == 0 ||
(pdata->pullup_ohm == 0 && pdata->connect ==
NTC_CONNECTED_GROUND) ||
(pdata->pulldown_ohm == 0 && pdata->connect ==
@ -341,7 +452,7 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
(pdata->connect != NTC_CONNECTED_POSITIVE &&
pdata->connect != NTC_CONNECTED_GROUND))) {
dev_err(&pdev->dev,
"Required data to use read_uV not supplied.\n");
"Required data to use read_uv not supplied.\n");
return -EINVAL;
}
@ -349,11 +460,13 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
if (!data)
return -ENOMEM;
pdev_id = of_id ? of_id->data : platform_get_device_id(pdev);
data->dev = &pdev->dev;
data->pdata = pdata;
strlcpy(data->name, pdev->id_entry->name, sizeof(data->name));
strlcpy(data->name, pdev_id->name, sizeof(data->name));
switch (pdev->id_entry->driver_data) {
switch (pdev_id->driver_data) {
case TYPE_NCPXXWB473:
data->comp = ncpXXwb473;
data->n_comp = ARRAY_SIZE(ncpXXwb473);
@ -364,8 +477,7 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
break;
default:
dev_err(&pdev->dev, "Unknown device type: %lu(%s)\n",
pdev->id_entry->driver_data,
pdev->id_entry->name);
pdev_id->driver_data, pdev_id->name);
return -EINVAL;
}
@ -384,39 +496,34 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
goto err_after_sysfs;
}
dev_info(&pdev->dev, "Thermistor %s:%d (type: %s/%lu) successfully probed.\n",
pdev->name, pdev->id, pdev->id_entry->name,
pdev->id_entry->driver_data);
dev_info(&pdev->dev, "Thermistor type: %s successfully probed.\n",
pdev->name);
return 0;
err_after_sysfs:
sysfs_remove_group(&data->dev->kobj, &ntc_attr_group);
ntc_iio_channel_release(pdata);
return ret;
}
static int ntc_thermistor_remove(struct platform_device *pdev)
{
struct ntc_data *data = platform_get_drvdata(pdev);
struct ntc_thermistor_platform_data *pdata = data->pdata;
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&data->dev->kobj, &ntc_attr_group);
ntc_iio_channel_release(pdata);
platform_set_drvdata(pdev, NULL);
return 0;
}
static const struct platform_device_id ntc_thermistor_id[] = {
{ "ncp15wb473", TYPE_NCPXXWB473 },
{ "ncp18wb473", TYPE_NCPXXWB473 },
{ "ncp21wb473", TYPE_NCPXXWB473 },
{ "ncp03wb473", TYPE_NCPXXWB473 },
{ "ncp15wl333", TYPE_NCPXXWL333 },
{ },
};
static struct platform_driver ntc_thermistor_driver = {
.driver = {
.name = "ntc-thermistor",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(ntc_match),
},
.probe = ntc_thermistor_probe,
.remove = ntc_thermistor_remove,

View file

@ -1190,8 +1190,7 @@ static int __init pc87360_find(int sioaddr, u8 *devid,
confreg[3] = superio_inb(sioaddr, 0x25);
if (confreg[2] & 0x40) {
pr_info("Using thermistors for "
"temperature monitoring\n");
pr_info("Using thermistors for temperature monitoring\n");
}
if (confreg[3] & 0xE0) {
pr_info("VID inputs routed (mode %u)\n",
@ -1271,9 +1270,9 @@ static int pc87360_probe(struct platform_device *pdev)
if (data->address[i]
&& !devm_request_region(dev, extra_isa[i], PC87360_EXTENT,
pc87360_driver.driver.name)) {
dev_err(dev, "Region 0x%x-0x%x already "
"in use!\n", extra_isa[i],
extra_isa[i]+PC87360_EXTENT-1);
dev_err(dev,
"Region 0x%x-0x%x already in use!\n",
extra_isa[i], extra_isa[i]+PC87360_EXTENT-1);
return -EBUSY;
}
}
@ -1435,8 +1434,8 @@ static void pc87360_init_device(struct platform_device *pdev,
if (init >= 2 && data->innr) {
reg = pc87360_read_value(data, LD_IN, NO_BANK,
PC87365_REG_IN_CONVRATE);
dev_info(&pdev->dev, "VLM conversion set to "
"1s period, 160us delay\n");
dev_info(&pdev->dev,
"VLM conversion set to 1s period, 160us delay\n");
pc87360_write_value(data, LD_IN, NO_BANK,
PC87365_REG_IN_CONVRATE,
(reg & 0xC0) | 0x11);
@ -1450,8 +1449,8 @@ static void pc87360_init_device(struct platform_device *pdev,
if (init >= init_in[i]) {
/* Forcibly enable voltage channel */
if (!(reg & CHAN_ENA)) {
dev_dbg(&pdev->dev, "Forcibly "
"enabling in%d\n", i);
dev_dbg(&pdev->dev, "Forcibly enabling in%d\n",
i);
pc87360_write_value(data, LD_IN, i,
PC87365_REG_IN_STATUS,
(reg & 0x68) | 0x87);
@ -1575,8 +1574,8 @@ static void pc87360_autodiv(struct device *dev, int nr)
data->fan_status[nr] += 0x20;
data->fan_min[nr] >>= 1;
data->fan[nr] >>= 1;
dev_dbg(dev, "Increasing "
"clock divider to %d for fan %d\n",
dev_dbg(dev,
"Increasing clock divider to %d for fan %d\n",
FAN_DIV_FROM_REG(data->fan_status[nr]), nr + 1);
}
} else {
@ -1587,8 +1586,8 @@ static void pc87360_autodiv(struct device *dev, int nr)
data->fan_status[nr] -= 0x20;
data->fan_min[nr] <<= 1;
data->fan[nr] <<= 1;
dev_dbg(dev, "Decreasing "
"clock divider to %d for fan %d\n",
dev_dbg(dev,
"Decreasing clock divider to %d for fan %d\n",
FAN_DIV_FROM_REG(data->fan_status[nr]),
nr + 1);
}

View file

@ -627,8 +627,9 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute
pc87427_readall_pwm(data, nr);
mode = data->pwm_enable[nr] & PWM_ENABLE_MODE_MASK;
if (mode != PWM_MODE_MANUAL && mode != PWM_MODE_OFF) {
dev_notice(dev, "Can't set PWM%d duty cycle while not in "
"manual mode\n", nr + 1);
dev_notice(dev,
"Can't set PWM%d duty cycle while not in manual mode\n",
nr + 1);
mutex_unlock(&data->lock);
return -EPERM;
}
@ -1245,16 +1246,16 @@ static int __init pc87427_find(int sioaddr, struct pc87427_sio_data *sio_data)
val = superio_inb(sioaddr, SIOREG_MAP);
if (val & 0x01) {
pr_warn("Logical device 0x%02x is memory-mapped, "
"can't use\n", logdev[i]);
pr_warn("Logical device 0x%02x is memory-mapped, can't use\n",
logdev[i]);
continue;
}
val = (superio_inb(sioaddr, SIOREG_IOBASE) << 8)
| superio_inb(sioaddr, SIOREG_IOBASE + 1);
if (!val) {
pr_info("I/O base address not set for logical device "
"0x%02x\n", logdev[i]);
pr_info("I/O base address not set for logical device 0x%02x\n",
logdev[i]);
continue;
}
sio_data->address[i] = val;

View file

@ -42,17 +42,17 @@ config SENSORS_LM25066
default n
help
If you say yes here you get hardware monitoring support for National
Semiconductor LM25066, LM5064, and LM5066.
Semiconductor LM25056, LM25066, LM5064, and LM5066.
This driver can also be built as a module. If so, the module will
be called lm25066.
config SENSORS_LTC2978
tristate "Linear Technologies LTC2978 and LTC3880"
tristate "Linear Technologies LTC2974, LTC2978, LTC3880, and LTC3883"
default n
help
If you say yes here you get hardware monitoring support for Linear
Technology LTC2978 and LTC3880.
Technology LTC2974, LTC2978, LTC3880, and LTC3883.
This driver can also be built as a module. If so, the module will
be called ltc2978.

View file

@ -1,7 +1,8 @@
/*
* Hardware monitoring driver for LM25066 / LM5064 / LM5066
* Hardware monitoring driver for LM25056 / LM25066 / LM5064 / LM5066
*
* Copyright (c) 2011 Ericsson AB.
* Copyright (c) 2013 Guenter Roeck
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -26,7 +27,7 @@
#include <linux/i2c.h>
#include "pmbus.h"
enum chips { lm25066, lm5064, lm5066 };
enum chips { lm25056, lm25066, lm5064, lm5066 };
#define LM25066_READ_VAUX 0xd0
#define LM25066_MFR_READ_IIN 0xd1
@ -43,6 +44,138 @@ enum chips { lm25066, lm5064, lm5066 };
#define LM25066_DEV_SETUP_CL (1 << 4) /* Current limit */
/* LM25056 only */
#define LM25056_VAUX_OV_WARN_LIMIT 0xe3
#define LM25056_VAUX_UV_WARN_LIMIT 0xe4
#define LM25056_MFR_STS_VAUX_OV_WARN (1 << 1)
#define LM25056_MFR_STS_VAUX_UV_WARN (1 << 0)
struct __coeff {
short m, b, R;
};
#define PSC_CURRENT_IN_L (PSC_NUM_CLASSES)
#define PSC_POWER_L (PSC_NUM_CLASSES + 1)
static struct __coeff lm25066_coeff[4][PSC_NUM_CLASSES + 2] = {
[lm25056] = {
[PSC_VOLTAGE_IN] = {
.m = 16296,
.R = -2,
},
[PSC_CURRENT_IN] = {
.m = 13797,
.R = -2,
},
[PSC_CURRENT_IN_L] = {
.m = 6726,
.R = -2,
},
[PSC_POWER] = {
.m = 5501,
.R = -3,
},
[PSC_POWER_L] = {
.m = 26882,
.R = -4,
},
[PSC_TEMPERATURE] = {
.m = 1580,
.b = -14500,
.R = -2,
},
},
[lm25066] = {
[PSC_VOLTAGE_IN] = {
.m = 22070,
.R = -2,
},
[PSC_VOLTAGE_OUT] = {
.m = 22070,
.R = -2,
},
[PSC_CURRENT_IN] = {
.m = 13661,
.R = -2,
},
[PSC_CURRENT_IN_L] = {
.m = 6852,
.R = -2,
},
[PSC_POWER] = {
.m = 736,
.R = -2,
},
[PSC_POWER_L] = {
.m = 369,
.R = -2,
},
[PSC_TEMPERATURE] = {
.m = 16,
},
},
[lm5064] = {
[PSC_VOLTAGE_IN] = {
.m = 4611,
.R = -2,
},
[PSC_VOLTAGE_OUT] = {
.m = 4621,
.R = -2,
},
[PSC_CURRENT_IN] = {
.m = 10742,
.R = -2,
},
[PSC_CURRENT_IN_L] = {
.m = 5456,
.R = -2,
},
[PSC_POWER] = {
.m = 1204,
.R = -3,
},
[PSC_POWER_L] = {
.m = 612,
.R = -3,
},
[PSC_TEMPERATURE] = {
.m = 16,
},
},
[lm5066] = {
[PSC_VOLTAGE_IN] = {
.m = 4587,
.R = -2,
},
[PSC_VOLTAGE_OUT] = {
.m = 4587,
.R = -2,
},
[PSC_CURRENT_IN] = {
.m = 10753,
.R = -2,
},
[PSC_CURRENT_IN_L] = {
.m = 5405,
.R = -2,
},
[PSC_POWER] = {
.m = 1204,
.R = -3,
},
[PSC_POWER_L] = {
.m = 605,
.R = -3,
},
[PSC_TEMPERATURE] = {
.m = 16,
},
},
};
struct lm25066_data {
int id;
struct pmbus_driver_info info;
@ -56,42 +189,31 @@ static int lm25066_read_word_data(struct i2c_client *client, int page, int reg)
const struct lm25066_data *data = to_lm25066_data(info);
int ret;
if (page > 1)
return -ENXIO;
/* Map READ_VAUX into READ_VOUT register on page 1 */
if (page == 1) {
switch (reg) {
case PMBUS_READ_VOUT:
ret = pmbus_read_word_data(client, 0,
LM25066_READ_VAUX);
if (ret < 0)
break;
/* Adjust returned value to match VOUT coefficients */
switch (data->id) {
case lm25066:
/* VOUT: 4.54 mV VAUX: 283.2 uV LSB */
ret = DIV_ROUND_CLOSEST(ret * 2832, 45400);
break;
case lm5064:
/* VOUT: 4.53 mV VAUX: 700 uV LSB */
ret = DIV_ROUND_CLOSEST(ret * 70, 453);
break;
case lm5066:
/* VOUT: 2.18 mV VAUX: 725 uV LSB */
ret = DIV_ROUND_CLOSEST(ret * 725, 2180);
break;
}
switch (reg) {
case PMBUS_VIRT_READ_VMON:
ret = pmbus_read_word_data(client, 0, LM25066_READ_VAUX);
if (ret < 0)
break;
default:
/* No other valid registers on page 1 */
ret = -ENXIO;
/* Adjust returned value to match VIN coefficients */
switch (data->id) {
case lm25056:
/* VIN: 6.14 mV VAUX: 293 uV LSB */
ret = DIV_ROUND_CLOSEST(ret * 293, 6140);
break;
case lm25066:
/* VIN: 4.54 mV VAUX: 283.2 uV LSB */
ret = DIV_ROUND_CLOSEST(ret * 2832, 45400);
break;
case lm5064:
/* VIN: 4.53 mV VAUX: 700 uV LSB */
ret = DIV_ROUND_CLOSEST(ret * 70, 453);
break;
case lm5066:
/* VIN: 2.18 mV VAUX: 725 uV LSB */
ret = DIV_ROUND_CLOSEST(ret * 725, 2180);
break;
}
goto done;
}
switch (reg) {
break;
case PMBUS_READ_IIN:
ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_IIN);
break;
@ -128,7 +250,58 @@ static int lm25066_read_word_data(struct i2c_client *client, int page, int reg)
ret = -ENODATA;
break;
}
done:
return ret;
}
static int lm25056_read_word_data(struct i2c_client *client, int page, int reg)
{
int ret;
switch (reg) {
case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
ret = pmbus_read_word_data(client, 0,
LM25056_VAUX_UV_WARN_LIMIT);
if (ret < 0)
break;
/* Adjust returned value to match VIN coefficients */
ret = DIV_ROUND_CLOSEST(ret * 293, 6140);
break;
case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
ret = pmbus_read_word_data(client, 0,
LM25056_VAUX_OV_WARN_LIMIT);
if (ret < 0)
break;
/* Adjust returned value to match VIN coefficients */
ret = DIV_ROUND_CLOSEST(ret * 293, 6140);
break;
default:
ret = lm25066_read_word_data(client, page, reg);
break;
}
return ret;
}
static int lm25056_read_byte_data(struct i2c_client *client, int page, int reg)
{
int ret, s;
switch (reg) {
case PMBUS_VIRT_STATUS_VMON:
ret = pmbus_read_byte_data(client, 0,
PMBUS_STATUS_MFR_SPECIFIC);
if (ret < 0)
break;
s = 0;
if (ret & LM25056_MFR_STS_VAUX_UV_WARN)
s |= PB_VOLTAGE_UV_WARNING;
if (ret & LM25056_MFR_STS_VAUX_OV_WARN)
s |= PB_VOLTAGE_OV_WARNING;
ret = s;
break;
default:
ret = -ENODATA;
break;
}
return ret;
}
@ -137,19 +310,45 @@ static int lm25066_write_word_data(struct i2c_client *client, int page, int reg,
{
int ret;
if (page > 1)
return -ENXIO;
switch (reg) {
case PMBUS_VOUT_UV_WARN_LIMIT:
case PMBUS_OT_FAULT_LIMIT:
case PMBUS_OT_WARN_LIMIT:
case PMBUS_VIN_UV_WARN_LIMIT:
case PMBUS_VIN_OV_WARN_LIMIT:
word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
ret = pmbus_write_word_data(client, 0, reg, word);
pmbus_clear_cache(client);
break;
case PMBUS_IIN_OC_WARN_LIMIT:
word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
ret = pmbus_write_word_data(client, 0,
LM25066_MFR_IIN_OC_WARN_LIMIT,
word);
pmbus_clear_cache(client);
break;
case PMBUS_PIN_OP_WARN_LIMIT:
word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
ret = pmbus_write_word_data(client, 0,
LM25066_MFR_PIN_OP_WARN_LIMIT,
word);
pmbus_clear_cache(client);
break;
case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
/* Adjust from VIN coefficients (for LM25056) */
word = DIV_ROUND_CLOSEST((int)word * 6140, 293);
word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
ret = pmbus_write_word_data(client, 0,
LM25056_VAUX_UV_WARN_LIMIT, word);
pmbus_clear_cache(client);
break;
case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
/* Adjust from VIN coefficients (for LM25056) */
word = DIV_ROUND_CLOSEST((int)word * 6140, 293);
word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
ret = pmbus_write_word_data(client, 0,
LM25056_VAUX_OV_WARN_LIMIT, word);
pmbus_clear_cache(client);
break;
case PMBUS_VIRT_RESET_PIN_HISTORY:
ret = pmbus_write_byte(client, 0, LM25066_CLEAR_PIN_PEAK);
@ -161,23 +360,13 @@ static int lm25066_write_word_data(struct i2c_client *client, int page, int reg,
return ret;
}
static int lm25066_write_byte(struct i2c_client *client, int page, u8 value)
{
if (page > 1)
return -ENXIO;
if (page <= 0)
return pmbus_write_byte(client, page, value);
return 0;
}
static int lm25066_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int config;
struct lm25066_data *data;
struct pmbus_driver_info *info;
struct __coeff *coeff;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_READ_BYTE_DATA))
@ -195,107 +384,54 @@ static int lm25066_probe(struct i2c_client *client,
data->id = id->driver_data;
info = &data->info;
info->pages = 2;
info->pages = 1;
info->format[PSC_VOLTAGE_IN] = direct;
info->format[PSC_VOLTAGE_OUT] = direct;
info->format[PSC_CURRENT_IN] = direct;
info->format[PSC_TEMPERATURE] = direct;
info->format[PSC_POWER] = direct;
info->m[PSC_TEMPERATURE] = 16;
info->b[PSC_TEMPERATURE] = 0;
info->R[PSC_TEMPERATURE] = 0;
info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VMON
| PMBUS_HAVE_PIN | PMBUS_HAVE_IIN | PMBUS_HAVE_STATUS_INPUT
| PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT
| PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_PIN | PMBUS_HAVE_IIN
| PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
info->func[1] = PMBUS_HAVE_VOUT;
info->read_word_data = lm25066_read_word_data;
if (data->id == lm25056) {
info->func[0] |= PMBUS_HAVE_STATUS_VMON;
info->read_word_data = lm25056_read_word_data;
info->read_byte_data = lm25056_read_byte_data;
} else {
info->func[0] |= PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
info->read_word_data = lm25066_read_word_data;
}
info->write_word_data = lm25066_write_word_data;
info->write_byte = lm25066_write_byte;
switch (id->driver_data) {
case lm25066:
info->m[PSC_VOLTAGE_IN] = 22070;
info->b[PSC_VOLTAGE_IN] = 0;
info->R[PSC_VOLTAGE_IN] = -2;
info->m[PSC_VOLTAGE_OUT] = 22070;
info->b[PSC_VOLTAGE_OUT] = 0;
info->R[PSC_VOLTAGE_OUT] = -2;
if (config & LM25066_DEV_SETUP_CL) {
info->m[PSC_CURRENT_IN] = 6852;
info->b[PSC_CURRENT_IN] = 0;
info->R[PSC_CURRENT_IN] = -2;
info->m[PSC_POWER] = 369;
info->b[PSC_POWER] = 0;
info->R[PSC_POWER] = -2;
} else {
info->m[PSC_CURRENT_IN] = 13661;
info->b[PSC_CURRENT_IN] = 0;
info->R[PSC_CURRENT_IN] = -2;
info->m[PSC_POWER] = 736;
info->b[PSC_POWER] = 0;
info->R[PSC_POWER] = -2;
}
break;
case lm5064:
info->m[PSC_VOLTAGE_IN] = 22075;
info->b[PSC_VOLTAGE_IN] = 0;
info->R[PSC_VOLTAGE_IN] = -2;
info->m[PSC_VOLTAGE_OUT] = 22075;
info->b[PSC_VOLTAGE_OUT] = 0;
info->R[PSC_VOLTAGE_OUT] = -2;
if (config & LM25066_DEV_SETUP_CL) {
info->m[PSC_CURRENT_IN] = 6713;
info->b[PSC_CURRENT_IN] = 0;
info->R[PSC_CURRENT_IN] = -2;
info->m[PSC_POWER] = 3619;
info->b[PSC_POWER] = 0;
info->R[PSC_POWER] = -3;
} else {
info->m[PSC_CURRENT_IN] = 13426;
info->b[PSC_CURRENT_IN] = 0;
info->R[PSC_CURRENT_IN] = -2;
info->m[PSC_POWER] = 7238;
info->b[PSC_POWER] = 0;
info->R[PSC_POWER] = -3;
}
break;
case lm5066:
info->m[PSC_VOLTAGE_IN] = 4587;
info->b[PSC_VOLTAGE_IN] = 0;
info->R[PSC_VOLTAGE_IN] = -2;
info->m[PSC_VOLTAGE_OUT] = 4587;
info->b[PSC_VOLTAGE_OUT] = 0;
info->R[PSC_VOLTAGE_OUT] = -2;
if (config & LM25066_DEV_SETUP_CL) {
info->m[PSC_CURRENT_IN] = 10753;
info->b[PSC_CURRENT_IN] = 0;
info->R[PSC_CURRENT_IN] = -2;
info->m[PSC_POWER] = 1204;
info->b[PSC_POWER] = 0;
info->R[PSC_POWER] = -3;
} else {
info->m[PSC_CURRENT_IN] = 5405;
info->b[PSC_CURRENT_IN] = 0;
info->R[PSC_CURRENT_IN] = -2;
info->m[PSC_POWER] = 605;
info->b[PSC_POWER] = 0;
info->R[PSC_POWER] = -3;
}
break;
default:
return -ENODEV;
coeff = &lm25066_coeff[data->id][0];
info->m[PSC_TEMPERATURE] = coeff[PSC_TEMPERATURE].m;
info->b[PSC_TEMPERATURE] = coeff[PSC_TEMPERATURE].b;
info->R[PSC_TEMPERATURE] = coeff[PSC_TEMPERATURE].R;
info->m[PSC_VOLTAGE_IN] = coeff[PSC_VOLTAGE_IN].m;
info->b[PSC_VOLTAGE_IN] = coeff[PSC_VOLTAGE_IN].b;
info->R[PSC_VOLTAGE_IN] = coeff[PSC_VOLTAGE_IN].R;
info->m[PSC_VOLTAGE_OUT] = coeff[PSC_VOLTAGE_OUT].m;
info->b[PSC_VOLTAGE_OUT] = coeff[PSC_VOLTAGE_OUT].b;
info->R[PSC_VOLTAGE_OUT] = coeff[PSC_VOLTAGE_OUT].R;
info->b[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN].b;
info->R[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN].R;
info->b[PSC_POWER] = coeff[PSC_POWER].b;
info->R[PSC_POWER] = coeff[PSC_POWER].R;
if (config & LM25066_DEV_SETUP_CL) {
info->m[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN_L].m;
info->m[PSC_POWER] = coeff[PSC_POWER_L].m;
} else {
info->m[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN].m;
info->m[PSC_POWER] = coeff[PSC_POWER].m;
}
return pmbus_do_probe(client, id, info);
}
static const struct i2c_device_id lm25066_id[] = {
{"lm25056", lm25056},
{"lm25066", lm25066},
{"lm5064", lm5064},
{"lm5066", lm5066},
@ -317,5 +453,5 @@ static struct i2c_driver lm25066_driver = {
module_i2c_driver(lm25066_driver);
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for LM25066/LM5064/LM5066");
MODULE_DESCRIPTION("PMBus driver for LM25056/LM25066/LM5064/LM5066");
MODULE_LICENSE("GPL");

View file

@ -1,7 +1,8 @@
/*
* Hardware monitoring driver for LTC2978 and LTC3880
* Hardware monitoring driver for LTC2974, LTC2978, LTC3880, and LTC3883
*
* Copyright (c) 2011 Ericsson AB.
* Copyright (c) 2013 Guenter Roeck
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -26,28 +27,43 @@
#include <linux/i2c.h>
#include "pmbus.h"
enum chips { ltc2978, ltc3880 };
enum chips { ltc2974, ltc2978, ltc3880, ltc3883 };
/* LTC2978 and LTC3880 */
/* Common for all chips */
#define LTC2978_MFR_VOUT_PEAK 0xdd
#define LTC2978_MFR_VIN_PEAK 0xde
#define LTC2978_MFR_TEMPERATURE_PEAK 0xdf
#define LTC2978_MFR_SPECIAL_ID 0xe7
/* LTC2978 only */
/* LTC2974 and LTC2978 */
#define LTC2978_MFR_VOUT_MIN 0xfb
#define LTC2978_MFR_VIN_MIN 0xfc
#define LTC2978_MFR_TEMPERATURE_MIN 0xfd
/* LTC3880 only */
/* LTC2974 only */
#define LTC2974_MFR_IOUT_PEAK 0xd7
#define LTC2974_MFR_IOUT_MIN 0xd8
/* LTC3880 and LTC3883 */
#define LTC3880_MFR_IOUT_PEAK 0xd7
#define LTC3880_MFR_CLEAR_PEAKS 0xe3
#define LTC3880_MFR_TEMPERATURE2_PEAK 0xf4
/* LTC3883 only */
#define LTC3883_MFR_IIN_PEAK 0xe1
#define LTC2974_ID 0x0212
#define LTC2978_ID_REV1 0x0121
#define LTC2978_ID_REV2 0x0122
#define LTC3880_ID 0x4000
#define LTC3880_ID_MASK 0xff00
#define LTC3883_ID 0x4300
#define LTC3883_ID_MASK 0xff00
#define LTC2974_NUM_PAGES 4
#define LTC2978_NUM_PAGES 8
#define LTC3880_NUM_PAGES 2
#define LTC3883_NUM_PAGES 1
/*
* LTC2978 clears peak data whenever the CLEAR_FAULTS command is executed, which
@ -56,13 +72,15 @@ enum chips { ltc2978, ltc3880 };
* internal cache of measured peak data, which is only cleared if an explicit
* "clear peak" command is executed for the sensor in question.
*/
struct ltc2978_data {
enum chips id;
int vin_min, vin_max;
int temp_min, temp_max[2];
int vout_min[8], vout_max[8];
int iout_max[2];
int temp2_max;
u16 vin_min, vin_max;
u16 temp_min[LTC2974_NUM_PAGES], temp_max[LTC2974_NUM_PAGES];
u16 vout_min[LTC2978_NUM_PAGES], vout_max[LTC2978_NUM_PAGES];
u16 iout_min[LTC2974_NUM_PAGES], iout_max[LTC2974_NUM_PAGES];
u16 iin_max;
u16 temp2_max;
struct pmbus_driver_info info;
};
@ -167,9 +185,9 @@ static int ltc2978_read_word_data(struct i2c_client *client, int page, int reg)
LTC2978_MFR_TEMPERATURE_MIN);
if (ret >= 0) {
if (lin11_to_val(ret)
< lin11_to_val(data->temp_min))
data->temp_min = ret;
ret = data->temp_min;
< lin11_to_val(data->temp_min[page]))
data->temp_min[page] = ret;
ret = data->temp_min[page];
}
break;
case PMBUS_VIRT_READ_IOUT_MAX:
@ -185,6 +203,41 @@ static int ltc2978_read_word_data(struct i2c_client *client, int page, int reg)
return ret;
}
static int ltc2974_read_word_data(struct i2c_client *client, int page, int reg)
{
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
struct ltc2978_data *data = to_ltc2978_data(info);
int ret;
switch (reg) {
case PMBUS_VIRT_READ_IOUT_MAX:
ret = pmbus_read_word_data(client, page, LTC2974_MFR_IOUT_PEAK);
if (ret >= 0) {
if (lin11_to_val(ret)
> lin11_to_val(data->iout_max[page]))
data->iout_max[page] = ret;
ret = data->iout_max[page];
}
break;
case PMBUS_VIRT_READ_IOUT_MIN:
ret = pmbus_read_word_data(client, page, LTC2974_MFR_IOUT_MIN);
if (ret >= 0) {
if (lin11_to_val(ret)
< lin11_to_val(data->iout_min[page]))
data->iout_min[page] = ret;
ret = data->iout_min[page];
}
break;
case PMBUS_VIRT_RESET_IOUT_HISTORY:
ret = 0;
break;
default:
ret = ltc2978_read_word_data(client, page, reg);
break;
}
return ret;
}
static int ltc3880_read_word_data(struct i2c_client *client, int page, int reg)
{
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
@ -226,15 +279,41 @@ static int ltc3880_read_word_data(struct i2c_client *client, int page, int reg)
return ret;
}
static int ltc3883_read_word_data(struct i2c_client *client, int page, int reg)
{
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
struct ltc2978_data *data = to_ltc2978_data(info);
int ret;
switch (reg) {
case PMBUS_VIRT_READ_IIN_MAX:
ret = pmbus_read_word_data(client, page, LTC3883_MFR_IIN_PEAK);
if (ret >= 0) {
if (lin11_to_val(ret)
> lin11_to_val(data->iin_max))
data->iin_max = ret;
ret = data->iin_max;
}
break;
case PMBUS_VIRT_RESET_IIN_HISTORY:
ret = 0;
break;
default:
ret = ltc3880_read_word_data(client, page, reg);
break;
}
return ret;
}
static int ltc2978_clear_peaks(struct i2c_client *client, int page,
enum chips id)
{
int ret;
if (id == ltc2978)
ret = pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS);
else
if (id == ltc3880 || id == ltc3883)
ret = pmbus_write_byte(client, 0, LTC3880_MFR_CLEAR_PEAKS);
else
ret = pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS);
return ret;
}
@ -247,8 +326,13 @@ static int ltc2978_write_word_data(struct i2c_client *client, int page,
int ret;
switch (reg) {
case PMBUS_VIRT_RESET_IIN_HISTORY:
data->iin_max = 0x7c00;
ret = ltc2978_clear_peaks(client, page, data->id);
break;
case PMBUS_VIRT_RESET_IOUT_HISTORY:
data->iout_max[page] = 0x7c00;
data->iout_min[page] = 0xfbff;
ret = ltc2978_clear_peaks(client, page, data->id);
break;
case PMBUS_VIRT_RESET_TEMP2_HISTORY:
@ -266,7 +350,7 @@ static int ltc2978_write_word_data(struct i2c_client *client, int page,
ret = ltc2978_clear_peaks(client, page, data->id);
break;
case PMBUS_VIRT_RESET_TEMP_HISTORY:
data->temp_min = 0x7bff;
data->temp_min[page] = 0x7bff;
data->temp_max[page] = 0x7c00;
ret = ltc2978_clear_peaks(client, page, data->id);
break;
@ -278,8 +362,10 @@ static int ltc2978_write_word_data(struct i2c_client *client, int page,
}
static const struct i2c_device_id ltc2978_id[] = {
{"ltc2974", ltc2974},
{"ltc2978", ltc2978},
{"ltc3880", ltc3880},
{"ltc3883", ltc3883},
{}
};
MODULE_DEVICE_TABLE(i2c, ltc2978_id);
@ -304,10 +390,14 @@ static int ltc2978_probe(struct i2c_client *client,
if (chip_id < 0)
return chip_id;
if (chip_id == LTC2978_ID_REV1 || chip_id == LTC2978_ID_REV2) {
if (chip_id == LTC2974_ID) {
data->id = ltc2974;
} else if (chip_id == LTC2978_ID_REV1 || chip_id == LTC2978_ID_REV2) {
data->id = ltc2978;
} else if ((chip_id & LTC3880_ID_MASK) == LTC3880_ID) {
data->id = ltc3880;
} else if ((chip_id & LTC3883_ID_MASK) == LTC3883_ID) {
data->id = ltc3883;
} else {
dev_err(&client->dev, "Unsupported chip ID 0x%x\n", chip_id);
return -ENODEV;
@ -323,26 +413,45 @@ static int ltc2978_probe(struct i2c_client *client,
data->vin_min = 0x7bff;
data->vin_max = 0x7c00;
data->temp_min = 0x7bff;
for (i = 0; i < ARRAY_SIZE(data->vout_min); i++)
data->vout_min[i] = 0xffff;
for (i = 0; i < ARRAY_SIZE(data->iout_min); i++)
data->iout_min[i] = 0xfbff;
for (i = 0; i < ARRAY_SIZE(data->iout_max); i++)
data->iout_max[i] = 0x7c00;
for (i = 0; i < ARRAY_SIZE(data->temp_min); i++)
data->temp_min[i] = 0x7bff;
for (i = 0; i < ARRAY_SIZE(data->temp_max); i++)
data->temp_max[i] = 0x7c00;
data->temp2_max = 0x7c00;
switch (data->id) {
case ltc2974:
info->read_word_data = ltc2974_read_word_data;
info->pages = LTC2974_NUM_PAGES;
info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
| PMBUS_HAVE_TEMP2;
for (i = 0; i < info->pages; i++) {
info->func[i] |= PMBUS_HAVE_VOUT
| PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_POUT
| PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
}
break;
case ltc2978:
info->read_word_data = ltc2978_read_word_data;
info->pages = 8;
info->pages = LTC2978_NUM_PAGES;
info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
| PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
| PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
for (i = 1; i < 8; i++) {
for (i = 1; i < LTC2978_NUM_PAGES; i++) {
info->func[i] = PMBUS_HAVE_VOUT
| PMBUS_HAVE_STATUS_VOUT;
}
break;
case ltc3880:
info->read_word_data = ltc3880_read_word_data;
info->pages = 2;
info->pages = LTC3880_NUM_PAGES;
info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN
| PMBUS_HAVE_STATUS_INPUT
| PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
@ -353,15 +462,20 @@ static int ltc2978_probe(struct i2c_client *client,
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
| PMBUS_HAVE_POUT
| PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
data->iout_max[0] = 0x7c00;
data->iout_max[1] = 0x7c00;
break;
case ltc3883:
info->read_word_data = ltc3883_read_word_data;
info->pages = LTC3883_NUM_PAGES;
info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN
| PMBUS_HAVE_STATUS_INPUT
| PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
| PMBUS_HAVE_PIN | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
| PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;
break;
default:
return -ENODEV;
}
for (i = 0; i < info->pages; i++)
data->vout_min[i] = 0xffff;
return pmbus_do_probe(client, id, info);
}
@ -378,5 +492,5 @@ static struct i2c_driver ltc2978_driver = {
module_i2c_driver(ltc2978_driver);
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for LTC2978 and LTC3880");
MODULE_DESCRIPTION("PMBus driver for LTC2974, LTC2978, LTC3880, and LTC3883");
MODULE_LICENSE("GPL");

View file

@ -107,17 +107,14 @@ static ssize_t s3c_hwmon_show_raw(struct device *dev,
return (ret < 0) ? ret : snprintf(buf, PAGE_SIZE, "%d\n", ret);
}
#define DEF_ADC_ATTR(x) \
static SENSOR_DEVICE_ATTR(adc##x##_raw, S_IRUGO, s3c_hwmon_show_raw, NULL, x)
DEF_ADC_ATTR(0);
DEF_ADC_ATTR(1);
DEF_ADC_ATTR(2);
DEF_ADC_ATTR(3);
DEF_ADC_ATTR(4);
DEF_ADC_ATTR(5);
DEF_ADC_ATTR(6);
DEF_ADC_ATTR(7);
static SENSOR_DEVICE_ATTR(adc0_raw, S_IRUGO, s3c_hwmon_show_raw, NULL, 0);
static SENSOR_DEVICE_ATTR(adc1_raw, S_IRUGO, s3c_hwmon_show_raw, NULL, 1);
static SENSOR_DEVICE_ATTR(adc2_raw, S_IRUGO, s3c_hwmon_show_raw, NULL, 2);
static SENSOR_DEVICE_ATTR(adc3_raw, S_IRUGO, s3c_hwmon_show_raw, NULL, 3);
static SENSOR_DEVICE_ATTR(adc4_raw, S_IRUGO, s3c_hwmon_show_raw, NULL, 4);
static SENSOR_DEVICE_ATTR(adc5_raw, S_IRUGO, s3c_hwmon_show_raw, NULL, 5);
static SENSOR_DEVICE_ATTR(adc6_raw, S_IRUGO, s3c_hwmon_show_raw, NULL, 6);
static SENSOR_DEVICE_ATTR(adc7_raw, S_IRUGO, s3c_hwmon_show_raw, NULL, 7);
static struct attribute *s3c_hwmon_attrs[9] = {
&sensor_dev_attr_adc0_raw.dev_attr.attr,

View file

@ -161,8 +161,8 @@ static int sch56xx_send_cmd(u16 addr, u8 cmd, u16 reg, u8 v)
break;
}
if (i == max_busy_polls + max_lazy_polls) {
pr_err("Max retries exceeded reading virtual "
"register 0x%04hx (%d)\n", reg, 1);
pr_err("Max retries exceeded reading virtual register 0x%04hx (%d)\n",
reg, 1);
return -EIO;
}
@ -178,12 +178,12 @@ static int sch56xx_send_cmd(u16 addr, u8 cmd, u16 reg, u8 v)
break;
if (i == 0)
pr_warn("EC reports: 0x%02x reading virtual register "
"0x%04hx\n", (unsigned int)val, reg);
pr_warn("EC reports: 0x%02x reading virtual register 0x%04hx\n",
(unsigned int)val, reg);
}
if (i == max_busy_polls) {
pr_err("Max retries exceeded reading virtual "
"register 0x%04hx (%d)\n", reg, 2);
pr_err("Max retries exceeded reading virtual register 0x%04hx (%d)\n",
reg, 2);
return -EIO;
}

View file

@ -456,8 +456,9 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *da,
data->fan_div[nr] = 3;
break;
default:
dev_err(dev, "fan_div value %ld not "
"supported. Choose one of 1, 2, 4 or 8!\n", val);
dev_err(dev,
"fan_div value %ld not supported. Choose one of 1, 2, 4 or 8!\n",
val);
mutex_unlock(&data->update_lock);
return -EINVAL;
}

View file

@ -41,8 +41,8 @@ enum chips { thmc50, adm1022 };
static unsigned short adm1022_temp3[16];
static unsigned int adm1022_temp3_num;
module_param_array(adm1022_temp3, ushort, &adm1022_temp3_num, 0);
MODULE_PARM_DESC(adm1022_temp3, "List of adapter,address pairs "
"to enable 3rd temperature (ADM1022 only)");
MODULE_PARM_DESC(adm1022_temp3,
"List of adapter,address pairs to enable 3rd temperature (ADM1022 only)");
/* Many THMC50 constants specified below */
@ -312,8 +312,7 @@ static int thmc50_detect(struct i2c_client *client,
const char *type_name;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
pr_debug("thmc50: detect failed, "
"smbus byte data not supported!\n");
pr_debug("thmc50: detect failed, smbus byte data not supported!\n");
return -ENODEV;
}

View file

@ -155,8 +155,8 @@ static int tmp102_probe(struct i2c_client *client,
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_WORD_DATA)) {
dev_err(&client->dev, "adapter doesn't support SMBus word "
"transactions\n");
dev_err(&client->dev,
"adapter doesn't support SMBus word transactions\n");
return -ENODEV;
}

View file

@ -5,6 +5,9 @@
* Gabriel Konat, Sander Leget, Wouter Willems
* Copyright (C) 2009 Andre Prendel <andre.prendel@gmx.de>
*
* Cleanup and support for TMP431 and TMP432 by Guenter Roeck
* Copyright (c) 2013 Guenter Roeck <linux@roeck-us.net>
*
* 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
@ -30,6 +33,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/bitops.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
@ -40,9 +44,9 @@
#include <linux/sysfs.h>
/* Addresses to scan */
static const unsigned short normal_i2c[] = { 0x4c, I2C_CLIENT_END };
static const unsigned short normal_i2c[] = { 0x4c, 0x4d, 0x4e, I2C_CLIENT_END };
enum chips { tmp401, tmp411 };
enum chips { tmp401, tmp411, tmp431, tmp432 };
/*
* The TMP401 registers, note some registers have different addresses for
@ -54,42 +58,84 @@ enum chips { tmp401, tmp411 };
#define TMP401_CONVERSION_RATE_READ 0x04
#define TMP401_CONVERSION_RATE_WRITE 0x0A
#define TMP401_TEMP_CRIT_HYST 0x21
#define TMP401_CONSECUTIVE_ALERT 0x22
#define TMP401_MANUFACTURER_ID_REG 0xFE
#define TMP401_DEVICE_ID_REG 0xFF
#define TMP411_N_FACTOR_REG 0x18
static const u8 TMP401_TEMP_MSB[2] = { 0x00, 0x01 };
static const u8 TMP401_TEMP_LSB[2] = { 0x15, 0x10 };
static const u8 TMP401_TEMP_LOW_LIMIT_MSB_READ[2] = { 0x06, 0x08 };
static const u8 TMP401_TEMP_LOW_LIMIT_MSB_WRITE[2] = { 0x0C, 0x0E };
static const u8 TMP401_TEMP_LOW_LIMIT_LSB[2] = { 0x17, 0x14 };
static const u8 TMP401_TEMP_HIGH_LIMIT_MSB_READ[2] = { 0x05, 0x07 };
static const u8 TMP401_TEMP_HIGH_LIMIT_MSB_WRITE[2] = { 0x0B, 0x0D };
static const u8 TMP401_TEMP_HIGH_LIMIT_LSB[2] = { 0x16, 0x13 };
/* These are called the THERM limit / hysteresis / mask in the datasheet */
static const u8 TMP401_TEMP_CRIT_LIMIT[2] = { 0x20, 0x19 };
static const u8 TMP401_TEMP_MSB_READ[6][2] = {
{ 0x00, 0x01 }, /* temp */
{ 0x06, 0x08 }, /* low limit */
{ 0x05, 0x07 }, /* high limit */
{ 0x20, 0x19 }, /* therm (crit) limit */
{ 0x30, 0x34 }, /* lowest */
{ 0x32, 0x36 }, /* highest */
};
static const u8 TMP411_TEMP_LOWEST_MSB[2] = { 0x30, 0x34 };
static const u8 TMP411_TEMP_LOWEST_LSB[2] = { 0x31, 0x35 };
static const u8 TMP411_TEMP_HIGHEST_MSB[2] = { 0x32, 0x36 };
static const u8 TMP411_TEMP_HIGHEST_LSB[2] = { 0x33, 0x37 };
static const u8 TMP401_TEMP_MSB_WRITE[6][2] = {
{ 0, 0 }, /* temp (unused) */
{ 0x0C, 0x0E }, /* low limit */
{ 0x0B, 0x0D }, /* high limit */
{ 0x20, 0x19 }, /* therm (crit) limit */
{ 0x30, 0x34 }, /* lowest */
{ 0x32, 0x36 }, /* highest */
};
static const u8 TMP401_TEMP_LSB[6][2] = {
{ 0x15, 0x10 }, /* temp */
{ 0x17, 0x14 }, /* low limit */
{ 0x16, 0x13 }, /* high limit */
{ 0, 0 }, /* therm (crit) limit (unused) */
{ 0x31, 0x35 }, /* lowest */
{ 0x33, 0x37 }, /* highest */
};
static const u8 TMP432_TEMP_MSB_READ[4][3] = {
{ 0x00, 0x01, 0x23 }, /* temp */
{ 0x06, 0x08, 0x16 }, /* low limit */
{ 0x05, 0x07, 0x15 }, /* high limit */
{ 0x20, 0x19, 0x1A }, /* therm (crit) limit */
};
static const u8 TMP432_TEMP_MSB_WRITE[4][3] = {
{ 0, 0, 0 }, /* temp - unused */
{ 0x0C, 0x0E, 0x16 }, /* low limit */
{ 0x0B, 0x0D, 0x15 }, /* high limit */
{ 0x20, 0x19, 0x1A }, /* therm (crit) limit */
};
static const u8 TMP432_TEMP_LSB[3][3] = {
{ 0x29, 0x10, 0x24 }, /* temp */
{ 0x3E, 0x14, 0x18 }, /* low limit */
{ 0x3D, 0x13, 0x17 }, /* high limit */
};
/* [0] = fault, [1] = low, [2] = high, [3] = therm/crit */
static const u8 TMP432_STATUS_REG[] = {
0x1b, 0x36, 0x35, 0x37 };
/* Flags */
#define TMP401_CONFIG_RANGE 0x04
#define TMP401_CONFIG_SHUTDOWN 0x40
#define TMP401_STATUS_LOCAL_CRIT 0x01
#define TMP401_STATUS_REMOTE_CRIT 0x02
#define TMP401_STATUS_REMOTE_OPEN 0x04
#define TMP401_STATUS_REMOTE_LOW 0x08
#define TMP401_STATUS_REMOTE_HIGH 0x10
#define TMP401_STATUS_LOCAL_LOW 0x20
#define TMP401_STATUS_LOCAL_HIGH 0x40
#define TMP401_CONFIG_RANGE BIT(2)
#define TMP401_CONFIG_SHUTDOWN BIT(6)
#define TMP401_STATUS_LOCAL_CRIT BIT(0)
#define TMP401_STATUS_REMOTE_CRIT BIT(1)
#define TMP401_STATUS_REMOTE_OPEN BIT(2)
#define TMP401_STATUS_REMOTE_LOW BIT(3)
#define TMP401_STATUS_REMOTE_HIGH BIT(4)
#define TMP401_STATUS_LOCAL_LOW BIT(5)
#define TMP401_STATUS_LOCAL_HIGH BIT(6)
/* On TMP432, each status has its own register */
#define TMP432_STATUS_LOCAL BIT(0)
#define TMP432_STATUS_REMOTE1 BIT(1)
#define TMP432_STATUS_REMOTE2 BIT(2)
/* Manufacturer / Device ID's */
#define TMP401_MANUFACTURER_ID 0x55
#define TMP401_DEVICE_ID 0x11
#define TMP411_DEVICE_ID 0x12
#define TMP411A_DEVICE_ID 0x12
#define TMP411B_DEVICE_ID 0x13
#define TMP411C_DEVICE_ID 0x10
#define TMP431_DEVICE_ID 0x31
#define TMP432_DEVICE_ID 0x32
/*
* Driver data (common to all clients)
@ -98,6 +144,8 @@ static const u8 TMP411_TEMP_HIGHEST_LSB[2] = { 0x33, 0x37 };
static const struct i2c_device_id tmp401_id[] = {
{ "tmp401", tmp401 },
{ "tmp411", tmp411 },
{ "tmp431", tmp431 },
{ "tmp432", tmp432 },
{ }
};
MODULE_DEVICE_TABLE(i2c, tmp401_id);
@ -113,16 +161,13 @@ struct tmp401_data {
unsigned long last_updated; /* in jiffies */
enum chips kind;
unsigned int update_interval; /* in milliseconds */
/* register values */
u8 status;
u8 status[4];
u8 config;
u16 temp[2];
u16 temp_low[2];
u16 temp_high[2];
u8 temp_crit[2];
u16 temp[6][3];
u8 temp_crit_hyst;
u16 temp_lowest[2];
u16 temp_highest[2];
};
/*
@ -136,10 +181,10 @@ static int tmp401_register_to_temp(u16 reg, u8 config)
if (config & TMP401_CONFIG_RANGE)
temp -= 64 * 256;
return (temp * 625 + 80) / 160;
return DIV_ROUND_CLOSEST(temp * 125, 32);
}
static u16 tmp401_temp_to_register(long temp, u8 config)
static u16 tmp401_temp_to_register(long temp, u8 config, int zbits)
{
if (config & TMP401_CONFIG_RANGE) {
temp = clamp_val(temp, -64000, 191000);
@ -147,134 +192,127 @@ static u16 tmp401_temp_to_register(long temp, u8 config)
} else
temp = clamp_val(temp, 0, 127000);
return (temp * 160 + 312) / 625;
return DIV_ROUND_CLOSEST(temp * (1 << (8 - zbits)), 1000) << zbits;
}
static int tmp401_crit_register_to_temp(u8 reg, u8 config)
static int tmp401_update_device_reg16(struct i2c_client *client,
struct tmp401_data *data)
{
int temp = reg;
int i, j, val;
int num_regs = data->kind == tmp411 ? 6 : 4;
int num_sensors = data->kind == tmp432 ? 3 : 2;
if (config & TMP401_CONFIG_RANGE)
temp -= 64;
return temp * 1000;
}
static u8 tmp401_crit_temp_to_register(long temp, u8 config)
{
if (config & TMP401_CONFIG_RANGE) {
temp = clamp_val(temp, -64000, 191000);
temp += 64000;
} else
temp = clamp_val(temp, 0, 127000);
return (temp + 500) / 1000;
}
static struct tmp401_data *tmp401_update_device_reg16(
struct i2c_client *client, struct tmp401_data *data)
{
int i;
for (i = 0; i < 2; i++) {
/*
* High byte must be read first immediately followed
* by the low byte
*/
data->temp[i] = i2c_smbus_read_byte_data(client,
TMP401_TEMP_MSB[i]) << 8;
data->temp[i] |= i2c_smbus_read_byte_data(client,
TMP401_TEMP_LSB[i]);
data->temp_low[i] = i2c_smbus_read_byte_data(client,
TMP401_TEMP_LOW_LIMIT_MSB_READ[i]) << 8;
data->temp_low[i] |= i2c_smbus_read_byte_data(client,
TMP401_TEMP_LOW_LIMIT_LSB[i]);
data->temp_high[i] = i2c_smbus_read_byte_data(client,
TMP401_TEMP_HIGH_LIMIT_MSB_READ[i]) << 8;
data->temp_high[i] |= i2c_smbus_read_byte_data(client,
TMP401_TEMP_HIGH_LIMIT_LSB[i]);
data->temp_crit[i] = i2c_smbus_read_byte_data(client,
TMP401_TEMP_CRIT_LIMIT[i]);
if (data->kind == tmp411) {
data->temp_lowest[i] = i2c_smbus_read_byte_data(client,
TMP411_TEMP_LOWEST_MSB[i]) << 8;
data->temp_lowest[i] |= i2c_smbus_read_byte_data(
client, TMP411_TEMP_LOWEST_LSB[i]);
data->temp_highest[i] = i2c_smbus_read_byte_data(
client, TMP411_TEMP_HIGHEST_MSB[i]) << 8;
data->temp_highest[i] |= i2c_smbus_read_byte_data(
client, TMP411_TEMP_HIGHEST_LSB[i]);
for (i = 0; i < num_sensors; i++) { /* local / r1 / r2 */
for (j = 0; j < num_regs; j++) { /* temp / low / ... */
u8 regaddr;
/*
* High byte must be read first immediately followed
* by the low byte
*/
regaddr = data->kind == tmp432 ?
TMP432_TEMP_MSB_READ[j][i] :
TMP401_TEMP_MSB_READ[j][i];
val = i2c_smbus_read_byte_data(client, regaddr);
if (val < 0)
return val;
data->temp[j][i] = val << 8;
if (j == 3) /* crit is msb only */
continue;
regaddr = data->kind == tmp432 ? TMP432_TEMP_LSB[j][i]
: TMP401_TEMP_LSB[j][i];
val = i2c_smbus_read_byte_data(client, regaddr);
if (val < 0)
return val;
data->temp[j][i] |= val;
}
}
return data;
return 0;
}
static struct tmp401_data *tmp401_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct tmp401_data *data = i2c_get_clientdata(client);
struct tmp401_data *ret = data;
int i, val;
unsigned long next_update;
mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
data->status = i2c_smbus_read_byte_data(client, TMP401_STATUS);
data->config = i2c_smbus_read_byte_data(client,
TMP401_CONFIG_READ);
tmp401_update_device_reg16(client, data);
next_update = data->last_updated +
msecs_to_jiffies(data->update_interval) + 1;
if (time_after(jiffies, next_update) || !data->valid) {
if (data->kind != tmp432) {
/*
* The driver uses the TMP432 status format internally.
* Convert status to TMP432 format for other chips.
*/
val = i2c_smbus_read_byte_data(client, TMP401_STATUS);
if (val < 0) {
ret = ERR_PTR(val);
goto abort;
}
data->status[0] =
(val & TMP401_STATUS_REMOTE_OPEN) >> 1;
data->status[1] =
((val & TMP401_STATUS_REMOTE_LOW) >> 2) |
((val & TMP401_STATUS_LOCAL_LOW) >> 5);
data->status[2] =
((val & TMP401_STATUS_REMOTE_HIGH) >> 3) |
((val & TMP401_STATUS_LOCAL_HIGH) >> 6);
data->status[3] = val & (TMP401_STATUS_LOCAL_CRIT
| TMP401_STATUS_REMOTE_CRIT);
} else {
for (i = 0; i < ARRAY_SIZE(data->status); i++) {
val = i2c_smbus_read_byte_data(client,
TMP432_STATUS_REG[i]);
if (val < 0) {
ret = ERR_PTR(val);
goto abort;
}
data->status[i] = val;
}
}
data->temp_crit_hyst = i2c_smbus_read_byte_data(client,
TMP401_TEMP_CRIT_HYST);
val = i2c_smbus_read_byte_data(client, TMP401_CONFIG_READ);
if (val < 0) {
ret = ERR_PTR(val);
goto abort;
}
data->config = val;
val = tmp401_update_device_reg16(client, data);
if (val < 0) {
ret = ERR_PTR(val);
goto abort;
}
val = i2c_smbus_read_byte_data(client, TMP401_TEMP_CRIT_HYST);
if (val < 0) {
ret = ERR_PTR(val);
goto abort;
}
data->temp_crit_hyst = val;
data->last_updated = jiffies;
data->valid = 1;
}
abort:
mutex_unlock(&data->update_lock);
return data;
return ret;
}
static ssize_t show_temp_value(struct device *dev,
struct device_attribute *devattr, char *buf)
static ssize_t show_temp(struct device *dev,
struct device_attribute *devattr, char *buf)
{
int index = to_sensor_dev_attr(devattr)->index;
int nr = to_sensor_dev_attr_2(devattr)->nr;
int index = to_sensor_dev_attr_2(devattr)->index;
struct tmp401_data *data = tmp401_update_device(dev);
return sprintf(buf, "%d\n",
tmp401_register_to_temp(data->temp[index], data->config));
}
static ssize_t show_temp_min(struct device *dev,
struct device_attribute *devattr, char *buf)
{
int index = to_sensor_dev_attr(devattr)->index;
struct tmp401_data *data = tmp401_update_device(dev);
if (IS_ERR(data))
return PTR_ERR(data);
return sprintf(buf, "%d\n",
tmp401_register_to_temp(data->temp_low[index], data->config));
}
static ssize_t show_temp_max(struct device *dev,
struct device_attribute *devattr, char *buf)
{
int index = to_sensor_dev_attr(devattr)->index;
struct tmp401_data *data = tmp401_update_device(dev);
return sprintf(buf, "%d\n",
tmp401_register_to_temp(data->temp_high[index], data->config));
}
static ssize_t show_temp_crit(struct device *dev,
struct device_attribute *devattr, char *buf)
{
int index = to_sensor_dev_attr(devattr)->index;
struct tmp401_data *data = tmp401_update_device(dev);
return sprintf(buf, "%d\n",
tmp401_crit_register_to_temp(data->temp_crit[index],
data->config));
tmp401_register_to_temp(data->temp[nr][index], data->config));
}
static ssize_t show_temp_crit_hyst(struct device *dev,
@ -283,122 +321,60 @@ static ssize_t show_temp_crit_hyst(struct device *dev,
int temp, index = to_sensor_dev_attr(devattr)->index;
struct tmp401_data *data = tmp401_update_device(dev);
if (IS_ERR(data))
return PTR_ERR(data);
mutex_lock(&data->update_lock);
temp = tmp401_crit_register_to_temp(data->temp_crit[index],
data->config);
temp = tmp401_register_to_temp(data->temp[3][index], data->config);
temp -= data->temp_crit_hyst * 1000;
mutex_unlock(&data->update_lock);
return sprintf(buf, "%d\n", temp);
}
static ssize_t show_temp_lowest(struct device *dev,
struct device_attribute *devattr, char *buf)
{
int index = to_sensor_dev_attr(devattr)->index;
struct tmp401_data *data = tmp401_update_device(dev);
return sprintf(buf, "%d\n",
tmp401_register_to_temp(data->temp_lowest[index],
data->config));
}
static ssize_t show_temp_highest(struct device *dev,
struct device_attribute *devattr, char *buf)
{
int index = to_sensor_dev_attr(devattr)->index;
struct tmp401_data *data = tmp401_update_device(dev);
return sprintf(buf, "%d\n",
tmp401_register_to_temp(data->temp_highest[index],
data->config));
}
static ssize_t show_status(struct device *dev,
struct device_attribute *devattr, char *buf)
{
int mask = to_sensor_dev_attr(devattr)->index;
int nr = to_sensor_dev_attr_2(devattr)->nr;
int mask = to_sensor_dev_attr_2(devattr)->index;
struct tmp401_data *data = tmp401_update_device(dev);
if (data->status & mask)
return sprintf(buf, "1\n");
else
return sprintf(buf, "0\n");
if (IS_ERR(data))
return PTR_ERR(data);
return sprintf(buf, "%d\n", !!(data->status[nr] & mask));
}
static ssize_t store_temp_min(struct device *dev, struct device_attribute
*devattr, const char *buf, size_t count)
static ssize_t store_temp(struct device *dev, struct device_attribute *devattr,
const char *buf, size_t count)
{
int index = to_sensor_dev_attr(devattr)->index;
int nr = to_sensor_dev_attr_2(devattr)->nr;
int index = to_sensor_dev_attr_2(devattr)->index;
struct i2c_client *client = to_i2c_client(dev);
struct tmp401_data *data = tmp401_update_device(dev);
long val;
u16 reg;
u8 regaddr;
if (IS_ERR(data))
return PTR_ERR(data);
if (kstrtol(buf, 10, &val))
return -EINVAL;
reg = tmp401_temp_to_register(val, data->config);
reg = tmp401_temp_to_register(val, data->config, nr == 3 ? 8 : 4);
mutex_lock(&data->update_lock);
i2c_smbus_write_byte_data(to_i2c_client(dev),
TMP401_TEMP_LOW_LIMIT_MSB_WRITE[index], reg >> 8);
i2c_smbus_write_byte_data(to_i2c_client(dev),
TMP401_TEMP_LOW_LIMIT_LSB[index], reg & 0xFF);
data->temp_low[index] = reg;
mutex_unlock(&data->update_lock);
return count;
}
static ssize_t store_temp_max(struct device *dev, struct device_attribute
*devattr, const char *buf, size_t count)
{
int index = to_sensor_dev_attr(devattr)->index;
struct tmp401_data *data = tmp401_update_device(dev);
long val;
u16 reg;
if (kstrtol(buf, 10, &val))
return -EINVAL;
reg = tmp401_temp_to_register(val, data->config);
mutex_lock(&data->update_lock);
i2c_smbus_write_byte_data(to_i2c_client(dev),
TMP401_TEMP_HIGH_LIMIT_MSB_WRITE[index], reg >> 8);
i2c_smbus_write_byte_data(to_i2c_client(dev),
TMP401_TEMP_HIGH_LIMIT_LSB[index], reg & 0xFF);
data->temp_high[index] = reg;
mutex_unlock(&data->update_lock);
return count;
}
static ssize_t store_temp_crit(struct device *dev, struct device_attribute
*devattr, const char *buf, size_t count)
{
int index = to_sensor_dev_attr(devattr)->index;
struct tmp401_data *data = tmp401_update_device(dev);
long val;
u8 reg;
if (kstrtol(buf, 10, &val))
return -EINVAL;
reg = tmp401_crit_temp_to_register(val, data->config);
mutex_lock(&data->update_lock);
i2c_smbus_write_byte_data(to_i2c_client(dev),
TMP401_TEMP_CRIT_LIMIT[index], reg);
data->temp_crit[index] = reg;
regaddr = data->kind == tmp432 ? TMP432_TEMP_MSB_WRITE[nr][index]
: TMP401_TEMP_MSB_WRITE[nr][index];
i2c_smbus_write_byte_data(client, regaddr, reg >> 8);
if (nr != 3) {
regaddr = data->kind == tmp432 ? TMP432_TEMP_LSB[nr][index]
: TMP401_TEMP_LSB[nr][index];
i2c_smbus_write_byte_data(client, regaddr, reg & 0xFF);
}
data->temp[nr][index] = reg;
mutex_unlock(&data->update_lock);
@ -413,6 +389,9 @@ static ssize_t store_temp_crit_hyst(struct device *dev, struct device_attribute
long val;
u8 reg;
if (IS_ERR(data))
return PTR_ERR(data);
if (kstrtol(buf, 10, &val))
return -EINVAL;
@ -422,13 +401,12 @@ static ssize_t store_temp_crit_hyst(struct device *dev, struct device_attribute
val = clamp_val(val, 0, 127000);
mutex_lock(&data->update_lock);
temp = tmp401_crit_register_to_temp(data->temp_crit[index],
data->config);
temp = tmp401_register_to_temp(data->temp[3][index], data->config);
val = clamp_val(val, temp - 255000, temp);
reg = ((temp - val) + 500) / 1000;
i2c_smbus_write_byte_data(to_i2c_client(dev),
TMP401_TEMP_CRIT_HYST, reg);
i2c_smbus_write_byte_data(to_i2c_client(dev), TMP401_TEMP_CRIT_HYST,
reg);
data->temp_crit_hyst = reg;
@ -445,54 +423,130 @@ static ssize_t store_temp_crit_hyst(struct device *dev, struct device_attribute
static ssize_t reset_temp_history(struct device *dev,
struct device_attribute *devattr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct tmp401_data *data = i2c_get_clientdata(client);
long val;
if (kstrtol(buf, 10, &val))
return -EINVAL;
if (val != 1) {
dev_err(dev, "temp_reset_history value %ld not"
" supported. Use 1 to reset the history!\n", val);
dev_err(dev,
"temp_reset_history value %ld not supported. Use 1 to reset the history!\n",
val);
return -EINVAL;
}
i2c_smbus_write_byte_data(to_i2c_client(dev),
TMP411_TEMP_LOWEST_MSB[0], val);
mutex_lock(&data->update_lock);
i2c_smbus_write_byte_data(client, TMP401_TEMP_MSB_WRITE[5][0], val);
data->valid = 0;
mutex_unlock(&data->update_lock);
return count;
}
static struct sensor_device_attribute tmp401_attr[] = {
SENSOR_ATTR(temp1_input, S_IRUGO, show_temp_value, NULL, 0),
SENSOR_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_min,
store_temp_min, 0),
SENSOR_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
store_temp_max, 0),
SENSOR_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp_crit,
store_temp_crit, 0),
SENSOR_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp_crit_hyst,
store_temp_crit_hyst, 0),
SENSOR_ATTR(temp1_min_alarm, S_IRUGO, show_status, NULL,
TMP401_STATUS_LOCAL_LOW),
SENSOR_ATTR(temp1_max_alarm, S_IRUGO, show_status, NULL,
TMP401_STATUS_LOCAL_HIGH),
SENSOR_ATTR(temp1_crit_alarm, S_IRUGO, show_status, NULL,
TMP401_STATUS_LOCAL_CRIT),
SENSOR_ATTR(temp2_input, S_IRUGO, show_temp_value, NULL, 1),
SENSOR_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp_min,
store_temp_min, 1),
SENSOR_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max,
store_temp_max, 1),
SENSOR_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp_crit,
store_temp_crit, 1),
SENSOR_ATTR(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, 1),
SENSOR_ATTR(temp2_fault, S_IRUGO, show_status, NULL,
TMP401_STATUS_REMOTE_OPEN),
SENSOR_ATTR(temp2_min_alarm, S_IRUGO, show_status, NULL,
TMP401_STATUS_REMOTE_LOW),
SENSOR_ATTR(temp2_max_alarm, S_IRUGO, show_status, NULL,
TMP401_STATUS_REMOTE_HIGH),
SENSOR_ATTR(temp2_crit_alarm, S_IRUGO, show_status, NULL,
TMP401_STATUS_REMOTE_CRIT),
static ssize_t show_update_interval(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct tmp401_data *data = i2c_get_clientdata(client);
return sprintf(buf, "%u\n", data->update_interval);
}
static ssize_t set_update_interval(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct tmp401_data *data = i2c_get_clientdata(client);
unsigned long val;
int err, rate;
err = kstrtoul(buf, 10, &val);
if (err)
return err;
/*
* For valid rates, interval can be calculated as
* interval = (1 << (7 - rate)) * 125;
* Rounded rate is therefore
* rate = 7 - __fls(interval * 4 / (125 * 3));
* Use clamp_val() to avoid overflows, and to ensure valid input
* for __fls.
*/
val = clamp_val(val, 125, 16000);
rate = 7 - __fls(val * 4 / (125 * 3));
mutex_lock(&data->update_lock);
i2c_smbus_write_byte_data(client, TMP401_CONVERSION_RATE_WRITE, rate);
data->update_interval = (1 << (7 - rate)) * 125;
mutex_unlock(&data->update_lock);
return count;
}
static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0);
static SENSOR_DEVICE_ATTR_2(temp1_min, S_IWUSR | S_IRUGO, show_temp,
store_temp, 1, 0);
static SENSOR_DEVICE_ATTR_2(temp1_max, S_IWUSR | S_IRUGO, show_temp,
store_temp, 2, 0);
static SENSOR_DEVICE_ATTR_2(temp1_crit, S_IWUSR | S_IRUGO, show_temp,
store_temp, 3, 0);
static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO,
show_temp_crit_hyst, store_temp_crit_hyst, 0);
static SENSOR_DEVICE_ATTR_2(temp1_min_alarm, S_IRUGO, show_status, NULL,
1, TMP432_STATUS_LOCAL);
static SENSOR_DEVICE_ATTR_2(temp1_max_alarm, S_IRUGO, show_status, NULL,
2, TMP432_STATUS_LOCAL);
static SENSOR_DEVICE_ATTR_2(temp1_crit_alarm, S_IRUGO, show_status, NULL,
3, TMP432_STATUS_LOCAL);
static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1);
static SENSOR_DEVICE_ATTR_2(temp2_min, S_IWUSR | S_IRUGO, show_temp,
store_temp, 1, 1);
static SENSOR_DEVICE_ATTR_2(temp2_max, S_IWUSR | S_IRUGO, show_temp,
store_temp, 2, 1);
static SENSOR_DEVICE_ATTR_2(temp2_crit, S_IWUSR | S_IRUGO, show_temp,
store_temp, 3, 1);
static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst,
NULL, 1);
static SENSOR_DEVICE_ATTR_2(temp2_fault, S_IRUGO, show_status, NULL,
0, TMP432_STATUS_REMOTE1);
static SENSOR_DEVICE_ATTR_2(temp2_min_alarm, S_IRUGO, show_status, NULL,
1, TMP432_STATUS_REMOTE1);
static SENSOR_DEVICE_ATTR_2(temp2_max_alarm, S_IRUGO, show_status, NULL,
2, TMP432_STATUS_REMOTE1);
static SENSOR_DEVICE_ATTR_2(temp2_crit_alarm, S_IRUGO, show_status, NULL,
3, TMP432_STATUS_REMOTE1);
static DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, show_update_interval,
set_update_interval);
static struct attribute *tmp401_attributes[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp1_min.dev_attr.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr,
&sensor_dev_attr_temp1_crit.dev_attr.attr,
&sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp2_input.dev_attr.attr,
&sensor_dev_attr_temp2_min.dev_attr.attr,
&sensor_dev_attr_temp2_max.dev_attr.attr,
&sensor_dev_attr_temp2_crit.dev_attr.attr,
&sensor_dev_attr_temp2_crit_hyst.dev_attr.attr,
&sensor_dev_attr_temp2_fault.dev_attr.attr,
&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
&dev_attr_update_interval.attr,
NULL
};
static const struct attribute_group tmp401_group = {
.attrs = tmp401_attributes,
};
/*
@ -502,12 +556,60 @@ static struct sensor_device_attribute tmp401_attr[] = {
* minimum and maximum register reset for both the local
* and remote channels.
*/
static struct sensor_device_attribute tmp411_attr[] = {
SENSOR_ATTR(temp1_highest, S_IRUGO, show_temp_highest, NULL, 0),
SENSOR_ATTR(temp1_lowest, S_IRUGO, show_temp_lowest, NULL, 0),
SENSOR_ATTR(temp2_highest, S_IRUGO, show_temp_highest, NULL, 1),
SENSOR_ATTR(temp2_lowest, S_IRUGO, show_temp_lowest, NULL, 1),
SENSOR_ATTR(temp_reset_history, S_IWUSR, NULL, reset_temp_history, 0),
static SENSOR_DEVICE_ATTR_2(temp1_lowest, S_IRUGO, show_temp, NULL, 4, 0);
static SENSOR_DEVICE_ATTR_2(temp1_highest, S_IRUGO, show_temp, NULL, 5, 0);
static SENSOR_DEVICE_ATTR_2(temp2_lowest, S_IRUGO, show_temp, NULL, 4, 1);
static SENSOR_DEVICE_ATTR_2(temp2_highest, S_IRUGO, show_temp, NULL, 5, 1);
static SENSOR_DEVICE_ATTR(temp_reset_history, S_IWUSR, NULL, reset_temp_history,
0);
static struct attribute *tmp411_attributes[] = {
&sensor_dev_attr_temp1_highest.dev_attr.attr,
&sensor_dev_attr_temp1_lowest.dev_attr.attr,
&sensor_dev_attr_temp2_highest.dev_attr.attr,
&sensor_dev_attr_temp2_lowest.dev_attr.attr,
&sensor_dev_attr_temp_reset_history.dev_attr.attr,
NULL
};
static const struct attribute_group tmp411_group = {
.attrs = tmp411_attributes,
};
static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2);
static SENSOR_DEVICE_ATTR_2(temp3_min, S_IWUSR | S_IRUGO, show_temp,
store_temp, 1, 2);
static SENSOR_DEVICE_ATTR_2(temp3_max, S_IWUSR | S_IRUGO, show_temp,
store_temp, 2, 2);
static SENSOR_DEVICE_ATTR_2(temp3_crit, S_IWUSR | S_IRUGO, show_temp,
store_temp, 3, 2);
static SENSOR_DEVICE_ATTR(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst,
NULL, 2);
static SENSOR_DEVICE_ATTR_2(temp3_fault, S_IRUGO, show_status, NULL,
0, TMP432_STATUS_REMOTE2);
static SENSOR_DEVICE_ATTR_2(temp3_min_alarm, S_IRUGO, show_status, NULL,
1, TMP432_STATUS_REMOTE2);
static SENSOR_DEVICE_ATTR_2(temp3_max_alarm, S_IRUGO, show_status, NULL,
2, TMP432_STATUS_REMOTE2);
static SENSOR_DEVICE_ATTR_2(temp3_crit_alarm, S_IRUGO, show_status, NULL,
3, TMP432_STATUS_REMOTE2);
static struct attribute *tmp432_attributes[] = {
&sensor_dev_attr_temp3_input.dev_attr.attr,
&sensor_dev_attr_temp3_min.dev_attr.attr,
&sensor_dev_attr_temp3_max.dev_attr.attr,
&sensor_dev_attr_temp3_crit.dev_attr.attr,
&sensor_dev_attr_temp3_crit_hyst.dev_attr.attr,
&sensor_dev_attr_temp3_fault.dev_attr.attr,
&sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp3_min_alarm.dev_attr.attr,
&sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
NULL
};
static const struct attribute_group tmp432_group = {
.attrs = tmp432_attributes,
};
/*
@ -517,9 +619,11 @@ static struct sensor_device_attribute tmp411_attr[] = {
static void tmp401_init_client(struct i2c_client *client)
{
int config, config_orig;
struct tmp401_data *data = i2c_get_clientdata(client);
/* Set the conversion rate to 2 Hz */
i2c_smbus_write_byte_data(client, TMP401_CONVERSION_RATE_WRITE, 5);
data->update_interval = 500;
/* Start conversions (disable shutdown if necessary) */
config = i2c_smbus_read_byte_data(client, TMP401_CONFIG_READ);
@ -554,11 +658,35 @@ static int tmp401_detect(struct i2c_client *client,
switch (reg) {
case TMP401_DEVICE_ID:
if (client->addr != 0x4c)
return -ENODEV;
kind = tmp401;
break;
case TMP411_DEVICE_ID:
case TMP411A_DEVICE_ID:
if (client->addr != 0x4c)
return -ENODEV;
kind = tmp411;
break;
case TMP411B_DEVICE_ID:
if (client->addr != 0x4d)
return -ENODEV;
kind = tmp411;
break;
case TMP411C_DEVICE_ID:
if (client->addr != 0x4e)
return -ENODEV;
kind = tmp411;
break;
case TMP431_DEVICE_ID:
if (client->addr == 0x4e)
return -ENODEV;
kind = tmp431;
break;
case TMP432_DEVICE_ID:
if (client->addr == 0x4e)
return -ENODEV;
kind = tmp432;
break;
default:
return -ENODEV;
}
@ -579,20 +707,19 @@ static int tmp401_detect(struct i2c_client *client,
static int tmp401_remove(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct tmp401_data *data = i2c_get_clientdata(client);
int i;
if (data->hwmon_dev)
hwmon_device_unregister(data->hwmon_dev);
for (i = 0; i < ARRAY_SIZE(tmp401_attr); i++)
device_remove_file(&client->dev, &tmp401_attr[i].dev_attr);
sysfs_remove_group(&dev->kobj, &tmp401_group);
if (data->kind == tmp411) {
for (i = 0; i < ARRAY_SIZE(tmp411_attr); i++)
device_remove_file(&client->dev,
&tmp411_attr[i].dev_attr);
}
if (data->kind == tmp411)
sysfs_remove_group(&dev->kobj, &tmp411_group);
if (data->kind == tmp432)
sysfs_remove_group(&dev->kobj, &tmp432_group);
return 0;
}
@ -600,12 +727,12 @@ static int tmp401_remove(struct i2c_client *client)
static int tmp401_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int i, err = 0;
struct device *dev = &client->dev;
int err;
struct tmp401_data *data;
const char *names[] = { "TMP401", "TMP411" };
const char *names[] = { "TMP401", "TMP411", "TMP431", "TMP432" };
data = devm_kzalloc(&client->dev, sizeof(struct tmp401_data),
GFP_KERNEL);
data = devm_kzalloc(dev, sizeof(struct tmp401_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
@ -617,31 +744,32 @@ static int tmp401_probe(struct i2c_client *client,
tmp401_init_client(client);
/* Register sysfs hooks */
for (i = 0; i < ARRAY_SIZE(tmp401_attr); i++) {
err = device_create_file(&client->dev,
&tmp401_attr[i].dev_attr);
err = sysfs_create_group(&dev->kobj, &tmp401_group);
if (err)
return err;
/* Register additional tmp411 sysfs hooks */
if (data->kind == tmp411) {
err = sysfs_create_group(&dev->kobj, &tmp411_group);
if (err)
goto exit_remove;
}
/* Register additional tmp411 sysfs hooks */
if (data->kind == tmp411) {
for (i = 0; i < ARRAY_SIZE(tmp411_attr); i++) {
err = device_create_file(&client->dev,
&tmp411_attr[i].dev_attr);
if (err)
goto exit_remove;
}
/* Register additional tmp432 sysfs hooks */
if (data->kind == tmp432) {
err = sysfs_create_group(&dev->kobj, &tmp432_group);
if (err)
goto exit_remove;
}
data->hwmon_dev = hwmon_device_register(&client->dev);
data->hwmon_dev = hwmon_device_register(dev);
if (IS_ERR(data->hwmon_dev)) {
err = PTR_ERR(data->hwmon_dev);
data->hwmon_dev = NULL;
goto exit_remove;
}
dev_info(&client->dev, "Detected TI %s chip\n", names[data->kind]);
dev_info(dev, "Detected TI %s chip\n", names[data->kind]);
return 0;

View file

@ -208,8 +208,8 @@ static int tmp421_init_client(struct i2c_client *client)
/* Start conversions (disable shutdown if necessary) */
config = i2c_smbus_read_byte_data(client, TMP421_CONFIG_REG_1);
if (config < 0) {
dev_err(&client->dev, "Could not read configuration"
" register (%d)\n", config);
dev_err(&client->dev,
"Could not read configuration register (%d)\n", config);
return -ENODEV;
}
@ -322,6 +322,5 @@ static struct i2c_driver tmp421_driver = {
module_i2c_driver(tmp421_driver);
MODULE_AUTHOR("Andre Prendel <andre.prendel@gmx.de>");
MODULE_DESCRIPTION("Texas Instruments TMP421/422/423 temperature sensor"
" driver");
MODULE_DESCRIPTION("Texas Instruments TMP421/422/423 temperature sensor driver");
MODULE_LICENSE("GPL");

View file

@ -125,7 +125,7 @@ static const u8 VIA686A_REG_TEMP_HYST[] = { 0x3a, 0x3e, 0x1e };
* (These conversions were contributed by Jonathan Teh Soon Yew
* <j.teh@iname.com>)
*/
static inline u8 IN_TO_REG(long val, int inNum)
static inline u8 IN_TO_REG(long val, int in_num)
{
/*
* To avoid floating point, we multiply constants by 10 (100 for +12V).
@ -134,29 +134,29 @@ static inline u8 IN_TO_REG(long val, int inNum)
* by an additional 10000 (100000 for +12V): 1000 for val and 10 (100)
* for the constants.
*/
if (inNum <= 1)
if (in_num <= 1)
return (u8) clamp_val((val * 21024 - 1205000) / 250000, 0, 255);
else if (inNum == 2)
else if (in_num == 2)
return (u8) clamp_val((val * 15737 - 1205000) / 250000, 0, 255);
else if (inNum == 3)
else if (in_num == 3)
return (u8) clamp_val((val * 10108 - 1205000) / 250000, 0, 255);
else
return (u8) clamp_val((val * 41714 - 12050000) / 2500000, 0,
255);
}
static inline long IN_FROM_REG(u8 val, int inNum)
static inline long IN_FROM_REG(u8 val, int in_num)
{
/*
* To avoid floating point, we multiply constants by 10 (100 for +12V).
* We also multiply them by 1000 because we want 0.001V/bit for the
* output value. Rounding is done.
*/
if (inNum <= 1)
if (in_num <= 1)
return (long) ((250000 * val + 1330000 + 21024 / 2) / 21024);
else if (inNum == 2)
else if (in_num == 2)
return (long) ((250000 * val + 1330000 + 15737 / 2) / 15737);
else if (inNum == 3)
else if (in_num == 3)
return (long) ((250000 * val + 1330000 + 10108 / 2) / 10108);
else
return (long) ((2500000 * val + 13300000 + 41714 / 2) / 41714);
@ -210,10 +210,10 @@ static inline u8 FAN_TO_REG(long rpm, int div)
* VIA register values 0-255. I *10 before rounding, so we get tenth-degree
* precision. (I could have done all 1024 values for our 10-bit readings,
* but the function is very linear in the useful range (0-80 deg C), so
* we'll just use linear interpolation for 10-bit readings.) So, tempLUT
* we'll just use linear interpolation for 10-bit readings.) So, temp_lut
* is the temp at via register values 0-255:
*/
static const s16 tempLUT[] = {
static const s16 temp_lut[] = {
-709, -688, -667, -646, -627, -607, -589, -570, -553, -536, -519,
-503, -487, -471, -456, -442, -428, -414, -400, -387, -375,
-362, -350, -339, -327, -316, -305, -295, -285, -275, -265,
@ -261,7 +261,7 @@ static const s16 tempLUT[] = {
* - 2.525453e-04*val^3 + 1.424593e-02*val^2 + 2.148941e+00*val +7.275808e+01)
* Note that n=161:
*/
static const u8 viaLUT[] = {
static const u8 via_lut[] = {
12, 12, 13, 14, 14, 15, 16, 16, 17, 18, 18, 19, 20, 20, 21, 22, 23,
23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40,
41, 43, 45, 46, 48, 49, 51, 53, 55, 57, 59, 60, 62, 64, 66,
@ -284,26 +284,26 @@ static const u8 viaLUT[] = {
*/
static inline u8 TEMP_TO_REG(long val)
{
return viaLUT[val <= -50000 ? 0 : val >= 110000 ? 160 :
return via_lut[val <= -50000 ? 0 : val >= 110000 ? 160 :
(val < 0 ? val - 500 : val + 500) / 1000 + 50];
}
/* for 8-bit temperature hyst and over registers */
#define TEMP_FROM_REG(val) ((long)tempLUT[val] * 100)
#define TEMP_FROM_REG(val) ((long)temp_lut[val] * 100)
/* for 10-bit temperature readings */
static inline long TEMP_FROM_REG10(u16 val)
{
u16 eightBits = val >> 2;
u16 twoBits = val & 3;
u16 eight_bits = val >> 2;
u16 two_bits = val & 3;
/* no interpolation for these */
if (twoBits == 0 || eightBits == 255)
return TEMP_FROM_REG(eightBits);
if (two_bits == 0 || eight_bits == 255)
return TEMP_FROM_REG(eight_bits);
/* do some linear interpolation */
return (tempLUT[eightBits] * (4 - twoBits) +
tempLUT[eightBits + 1] * twoBits) * 25;
return (temp_lut[eight_bits] * (4 - two_bits) +
temp_lut[eight_bits + 1] * two_bits) * 25;
}
#define DIV_FROM_REG(val) (1 << (val))
@ -889,8 +889,8 @@ static int via686a_pci_probe(struct pci_dev *dev,
address = val & ~(VIA686A_EXTENT - 1);
if (address == 0) {
dev_err(&dev->dev, "base address not set - upgrade BIOS "
"or use force_addr=0xaddr\n");
dev_err(&dev->dev,
"base address not set - upgrade BIOS or use force_addr=0xaddr\n");
return -ENODEV;
}
@ -899,8 +899,9 @@ static int via686a_pci_probe(struct pci_dev *dev,
return -ENODEV;
if (!(val & 0x0001)) {
if (!force_addr) {
dev_warn(&dev->dev, "Sensors disabled, enable "
"with force_addr=0x%x\n", address);
dev_warn(&dev->dev,
"Sensors disabled, enable with force_addr=0x%x\n",
address);
return -ENODEV;
}

View file

@ -571,8 +571,9 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *attr,
break;
default:
count = -EINVAL;
dev_warn(dev, "fan div value %ld not supported. "
"Choose one of 1, 2, 4, or 8.\n", val);
dev_warn(dev,
"fan div value %ld not supported. Choose one of 1, 2, 4, or 8.\n",
val);
goto EXIT;
}
vt1211_write8(data, VT1211_REG_FAN_DIV,
@ -674,8 +675,9 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
break;
default:
count = -EINVAL;
dev_warn(dev, "pwm mode %ld not supported. "
"Choose one of 0 or 2.\n", val);
dev_warn(dev,
"pwm mode %ld not supported. Choose one of 0 or 2.\n",
val);
goto EXIT;
}
vt1211_write8(data, VT1211_REG_PWM_CTL,
@ -700,8 +702,9 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
case SHOW_SET_PWM_AUTO_CHANNELS_TEMP:
if (val < 1 || val > 7) {
count = -EINVAL;
dev_warn(dev, "temp channel %ld not supported. "
"Choose a value between 1 and 7.\n", val);
dev_warn(dev,
"temp channel %ld not supported. Choose a value between 1 and 7.\n",
val);
goto EXIT;
}
if (!ISTEMP(val - 1, data->uch_config)) {
@ -1325,15 +1328,15 @@ static int __init vt1211_init(void)
if ((uch_config < -1) || (uch_config > 31)) {
err = -EINVAL;
pr_warn("Invalid UCH configuration %d. "
"Choose a value between 0 and 31.\n", uch_config);
pr_warn("Invalid UCH configuration %d. Choose a value between 0 and 31.\n",
uch_config);
goto EXIT;
}
if ((int_mode < -1) || (int_mode > 0)) {
err = -EINVAL;
pr_warn("Invalid interrupt mode %d. "
"Only mode 0 is supported.\n", int_mode);
pr_warn("Invalid interrupt mode %d. Only mode 0 is supported.\n",
int_mode);
goto EXIT;
}

View file

@ -573,8 +573,9 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
data->fan_div[nr] = 3;
break;
default:
dev_err(dev, "fan_div value %ld not supported. "
"Choose one of 1, 2, 4 or 8!\n", val);
dev_err(dev,
"fan_div value %ld not supported. Choose one of 1, 2, 4 or 8!\n",
val);
mutex_unlock(&data->update_lock);
return -EINVAL;
}

View file

@ -840,8 +840,8 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
&& (reg >= 0xff || (sio_data->kind == nct6775
&& reg == 0x00))
&& data->fan_div[i] < 0x07) {
dev_dbg(dev, "Increasing fan%d "
"clock divider from %u to %u\n",
dev_dbg(dev,
"Increasing fan%d clock divider from %u to %u\n",
i + 1, div_from_reg(data->fan_div[i]),
div_from_reg(data->fan_div[i] + 1));
data->fan_div[i]++;
@ -1110,9 +1110,9 @@ store_fan_min(struct device *dev, struct device_attribute *attr,
*/
data->fan_min[nr] = 254;
new_div = 7; /* 128 == (1 << 7) */
dev_warn(dev, "fan%u low limit %lu below minimum %u, set to "
"minimum\n", nr + 1, val,
data->fan_from_reg_min(254, 7));
dev_warn(dev,
"fan%u low limit %lu below minimum %u, set to minimum\n",
nr + 1, val, data->fan_from_reg_min(254, 7));
} else if (!reg) {
/*
* Speed above this value cannot possibly be represented,
@ -1120,9 +1120,9 @@ store_fan_min(struct device *dev, struct device_attribute *attr,
*/
data->fan_min[nr] = 1;
new_div = 0; /* 1 == (1 << 0) */
dev_warn(dev, "fan%u low limit %lu above maximum %u, set to "
"maximum\n", nr + 1, val,
data->fan_from_reg_min(1, 0));
dev_warn(dev,
"fan%u low limit %lu above maximum %u, set to maximum\n",
nr + 1, val, data->fan_from_reg_min(1, 0));
} else {
/*
* Automatically pick the best divider, i.e. the one such
@ -2396,15 +2396,15 @@ static int w83627ehf_probe(struct platform_device *pdev)
en_vrm10 = superio_inb(sio_data->sioreg,
SIO_REG_EN_VRM10);
if ((en_vrm10 & 0x08) && data->vrm == 90) {
dev_warn(dev, "Setting VID input "
"voltage to TTL\n");
dev_warn(dev,
"Setting VID input voltage to TTL\n");
superio_outb(sio_data->sioreg,
SIO_REG_EN_VRM10,
en_vrm10 & ~0x08);
} else if (!(en_vrm10 & 0x08)
&& data->vrm == 100) {
dev_warn(dev, "Setting VID input "
"voltage to VRM10\n");
dev_warn(dev,
"Setting VID input voltage to VRM10\n");
superio_outb(sio_data->sioreg,
SIO_REG_EN_VRM10,
en_vrm10 | 0x08);
@ -2420,8 +2420,8 @@ static int w83627ehf_probe(struct platform_device *pdev)
if (err)
goto exit_release;
} else {
dev_info(dev, "VID pins in output mode, CPU VID not "
"available\n");
dev_info(dev,
"VID pins in output mode, CPU VID not available\n");
}
}
@ -2795,8 +2795,7 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr,
/* Activate logical device if needed */
val = superio_inb(sioaddr, SIO_REG_ENABLE);
if (!(val & 0x01)) {
pr_warn("Forcibly enabling Super-I/O. "
"Sensor is probably unusable.\n");
pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
}

View file

@ -64,8 +64,8 @@ enum chips { w83781d, w83782d, w83783s, as99127f };
/* Insmod parameters */
static unsigned short force_subclients[4];
module_param_array(force_subclients, short, NULL, 0);
MODULE_PARM_DESC(force_subclients, "List of subclient addresses: "
"{bus, clientaddr, subclientaddr1, subclientaddr2}");
MODULE_PARM_DESC(force_subclients,
"List of subclient addresses: {bus, clientaddr, subclientaddr1, subclientaddr2}");
static bool reset;
module_param(reset, bool, 0);
@ -826,8 +826,9 @@ store_sensor(struct device *dev, struct device_attribute *da,
data->sens[nr] = val;
break;
case W83781D_DEFAULT_BETA:
dev_warn(dev, "Sensor type %d is deprecated, please use 4 "
"instead\n", W83781D_DEFAULT_BETA);
dev_warn(dev,
"Sensor type %d is deprecated, please use 4 instead\n",
W83781D_DEFAULT_BETA);
/* fall through */
case 4: /* thermistor */
tmp = w83781d_read_value(data, W83781D_REG_SCFG1);
@ -874,8 +875,8 @@ w83781d_detect_subclients(struct i2c_client *new_client)
for (i = 2; i <= 3; i++) {
if (force_subclients[i] < 0x48 ||
force_subclients[i] > 0x4f) {
dev_err(&new_client->dev, "Invalid subclient "
"address %d; must be 0x48-0x4f\n",
dev_err(&new_client->dev,
"Invalid subclient address %d; must be 0x48-0x4f\n",
force_subclients[i]);
err = -EINVAL;
goto ERROR_SC_1;
@ -910,9 +911,9 @@ w83781d_detect_subclients(struct i2c_client *new_client)
for (i = 0; i < num_sc; i++) {
data->lm75[i] = i2c_new_dummy(adapter, sc_addr[i]);
if (!data->lm75[i]) {
dev_err(&new_client->dev, "Subclient %d "
"registration at address 0x%x "
"failed.\n", i, sc_addr[i]);
dev_err(&new_client->dev,
"Subclient %d registration at address 0x%x failed.\n",
i, sc_addr[i]);
err = -ENOMEM;
if (i == 1)
goto ERROR_SC_3;
@ -1176,8 +1177,9 @@ w83781d_detect(struct i2c_client *client, struct i2c_board_info *info)
goto err_nodev;
if (val1 <= 0x30 && w83781d_alias_detect(client, val1)) {
dev_dbg(&adapter->dev, "Device at 0x%02x appears to "
"be the same as ISA device\n", address);
dev_dbg(&adapter->dev,
"Device at 0x%02x appears to be the same as ISA device\n",
address);
goto err_nodev;
}
@ -1367,8 +1369,8 @@ w83781d_init_device(struct device *dev)
* as I see very little reason why this would be needed at
* all.
*/
dev_info(dev, "If reset=1 solved a problem you were "
"having, please report!\n");
dev_info(dev,
"If reset=1 solved a problem you were having, please report!\n");
/* save these registers */
i = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG);
@ -1425,8 +1427,8 @@ w83781d_init_device(struct device *dev)
/* Enable temp2 */
tmp = w83781d_read_value(data, W83781D_REG_TEMP2_CONFIG);
if (tmp & 0x01) {
dev_warn(dev, "Enabling temp2, readings "
"might not make sense\n");
dev_warn(dev,
"Enabling temp2, readings might not make sense\n");
w83781d_write_value(data, W83781D_REG_TEMP2_CONFIG,
tmp & 0xfe);
}
@ -1436,8 +1438,8 @@ w83781d_init_device(struct device *dev)
tmp = w83781d_read_value(data,
W83781D_REG_TEMP3_CONFIG);
if (tmp & 0x01) {
dev_warn(dev, "Enabling temp3, "
"readings might not make sense\n");
dev_warn(dev,
"Enabling temp3, readings might not make sense\n");
w83781d_write_value(data,
W83781D_REG_TEMP3_CONFIG, tmp & 0xfe);
}

View file

@ -56,8 +56,8 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
static unsigned short force_subclients[4];
module_param_array(force_subclients, short, NULL, 0);
MODULE_PARM_DESC(force_subclients, "List of subclient addresses: "
"{bus, clientaddr, subclientaddr1, subclientaddr2}");
MODULE_PARM_DESC(force_subclients,
"List of subclient addresses: {bus, clientaddr, subclientaddr1, subclientaddr2}");
static bool reset;
module_param(reset, bool, 0);

View file

@ -54,8 +54,8 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
static unsigned short force_subclients[4];
module_param_array(force_subclients, short, NULL, 0);
MODULE_PARM_DESC(force_subclients, "List of subclient addresses: "
"{bus, clientaddr, subclientaddr1, subclientaddr2}");
MODULE_PARM_DESC(force_subclients,
"List of subclient addresses: {bus, clientaddr, subclientaddr1, subclientaddr2}");
static bool init;
module_param(init, bool, 0);
@ -951,8 +951,8 @@ w83792d_detect_subclients(struct i2c_client *new_client)
for (i = 2; i <= 3; i++) {
if (force_subclients[i] < 0x48 ||
force_subclients[i] > 0x4f) {
dev_err(&new_client->dev, "invalid subclient "
"address %d; must be 0x48-0x4f\n",
dev_err(&new_client->dev,
"invalid subclient address %d; must be 0x48-0x4f\n",
force_subclients[i]);
err = -ENODEV;
goto ERROR_SC_0;
@ -969,8 +969,9 @@ w83792d_detect_subclients(struct i2c_client *new_client)
if (!(val & 0x80)) {
if ((data->lm75[0] != NULL) &&
((val & 0x7) == ((val >> 4) & 0x7))) {
dev_err(&new_client->dev, "duplicate addresses 0x%x, "
"use force_subclient\n", data->lm75[0]->addr);
dev_err(&new_client->dev,
"duplicate addresses 0x%x, use force_subclient\n",
data->lm75[0]->addr);
err = -ENODEV;
goto ERROR_SC_1;
}

View file

@ -59,8 +59,8 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
static unsigned short force_subclients[4];
module_param_array(force_subclients, short, NULL, 0);
MODULE_PARM_DESC(force_subclients, "List of subclient addresses: "
"{bus, clientaddr, subclientaddr1, subclientaddr2}");
MODULE_PARM_DESC(force_subclients,
"List of subclient addresses: {bus, clientaddr, subclientaddr1, subclientaddr2}");
static bool reset;
module_param(reset, bool, 0);
@ -1921,8 +1921,8 @@ static int w83793_probe(struct i2c_client *client,
}
if (i == ARRAY_SIZE(watchdog_minors)) {
data->watchdog_miscdev.minor = 0;
dev_warn(&client->dev, "Couldn't register watchdog chardev "
"(due to no free minor)\n");
dev_warn(&client->dev,
"Couldn't register watchdog chardev (due to no free minor)\n");
}
mutex_unlock(&watchdog_data_mutex);

View file

@ -2120,11 +2120,12 @@ static void w83795_check_dynamic_in_limits(struct i2c_client *client)
&w83795_in[i][3].dev_attr.attr,
S_IRUGO);
if (err_max || err_min)
dev_warn(&client->dev, "Failed to set in%d limits "
"read-only (%d, %d)\n", i, err_max, err_min);
dev_warn(&client->dev,
"Failed to set in%d limits read-only (%d, %d)\n",
i, err_max, err_min);
else
dev_info(&client->dev, "in%d limits set dynamically "
"from VID\n", i);
dev_info(&client->dev,
"in%d limits set dynamically from VID\n", i);
}
}

View file

@ -21,6 +21,8 @@
#ifndef _LINUX_NTC_H
#define _LINUX_NTC_H
struct iio_channel;
enum ntc_thermistor_type {
TYPE_NCPXXWB473,
TYPE_NCPXXWL333,
@ -39,13 +41,17 @@ struct ntc_thermistor_platform_data {
* described at Documentation/hwmon/ntc_thermistor
*
* pullup/down_ohm: 0 for infinite / not-connected
*
* chan: iio_channel pointer to communicate with the ADC which the
* thermistor is using for conversion of the analog values.
*/
int (*read_uV)(void);
unsigned int pullup_uV;
int (*read_uv)(struct ntc_thermistor_platform_data *);
unsigned int pullup_uv;
unsigned int pullup_ohm;
unsigned int pulldown_ohm;
enum { NTC_CONNECTED_POSITIVE, NTC_CONNECTED_GROUND } connect;
struct iio_channel *chan;
int (*read_ohm)(void);
};