Merge tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging
Pull hwmon updates from Guenter Roeck: - New drivers for MAX6697 and compatibles and for INA209. - Added support for IT8771E, IT8772E, MAX34460, MAX34461, MCP98244, and ADT7420 to existing drivers. - Added support for additional attributes to various drivers. - Replaced SENSORS_LIMIT with clamp_val; retire SENSORS_LIMIT; - Clean up PMBus code to reduce its size; clean up adt7410 driver. - A couple of minor bug fixes as well as documentation cleanup. - Out-of-tree change: Replace SENSORS_LIMIT with clamp_val in platform/x86/eeepc-laptop driver. * tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (32 commits) hwmon: (ntc_thermistor): Fix sparse warnings hwmon: (adt7410) Add device table entry for the adt7420 hwmon: (adt7410) Use I2C_ADDRS helper macro hwmon: (adt7410) Use the SIMPLE_DEV_PM_OPS helper macro hwmon: (adt7410) Let suspend/resume depend on CONFIG_PM_SLEEP hwmon: (adt7410) Clear unwanted bits in the config register hwmon: (jc42) Add support for MCP98244 hwmon: (pmbus) Clean up for code size reduction hwmon: (pmbus/max34440) Add support for MAX34460 and MAX34461 hwmon: (pmbus) Add support for word status register hwmon: (pmbus/zl6100) Add support for VMON/VDRV hwmon: (pmbus) Add function to clear sensor cache hwmon: (pmbus) Add support for additional voltage sensor hwmon: (pmbus) Use krealloc to allocate attribute memory hwmon: (pmbus) Simplify memory allocation for sensor attributes hwmon: (pmbus) Improve boolean handling hwmon: (pmbus) Simplify memory allocation for labels and booleans hwmon: (pmbus) Use dev variable to represent client->dev hwmon: (pmbus) Fix 'Macros with multiple statements' checkpatch error hwmon: (pmbus) Drop unnecessary error messages in probe error path ...
This commit is contained in:
18
Documentation/devicetree/bindings/i2c/ina209.txt
Normal file
18
Documentation/devicetree/bindings/i2c/ina209.txt
Normal file
@@ -0,0 +1,18 @@
|
||||
ina209 properties
|
||||
|
||||
Required properties:
|
||||
- compatible: Must be "ti,ina209"
|
||||
- reg: I2C address
|
||||
|
||||
Optional properties:
|
||||
|
||||
- shunt-resistor
|
||||
Shunt resistor value in micro-Ohm
|
||||
|
||||
Example:
|
||||
|
||||
temp-sensor@4c {
|
||||
compatible = "ti,ina209";
|
||||
reg = <0x4c>;
|
||||
shunt-resistor = <5000>;
|
||||
};
|
64
Documentation/devicetree/bindings/i2c/max6697.txt
Normal file
64
Documentation/devicetree/bindings/i2c/max6697.txt
Normal file
@@ -0,0 +1,64 @@
|
||||
max6697 properties
|
||||
|
||||
Required properties:
|
||||
- compatible:
|
||||
Should be one of
|
||||
maxim,max6581
|
||||
maxim,max6602
|
||||
maxim,max6622
|
||||
maxim,max6636
|
||||
maxim,max6689
|
||||
maxim,max6693
|
||||
maxim,max6694
|
||||
maxim,max6697
|
||||
maxim,max6698
|
||||
maxim,max6699
|
||||
- reg: I2C address
|
||||
|
||||
Optional properties:
|
||||
|
||||
- smbus-timeout-disable
|
||||
Set to disable SMBus timeout. If not specified, SMBus timeout will be
|
||||
enabled.
|
||||
- extended-range-enable
|
||||
Only valid for MAX6581. Set to enable extended temperature range.
|
||||
Extended temperature will be disabled if not specified.
|
||||
- beta-compensation-enable
|
||||
Only valid for MAX6693 and MX6694. Set to enable beta compensation on
|
||||
remote temperature channel 1.
|
||||
Beta compensation will be disabled if not specified.
|
||||
- alert-mask
|
||||
Alert bit mask. Alert disabled for bits set.
|
||||
Select bit 0 for local temperature, bit 1..7 for remote temperatures.
|
||||
If not specified, alert will be enabled for all channels.
|
||||
- over-temperature-mask
|
||||
Over-temperature bit mask. Over-temperature reporting disabled for
|
||||
bits set.
|
||||
Select bit 0 for local temperature, bit 1..7 for remote temperatures.
|
||||
If not specified, over-temperature reporting will be enabled for all
|
||||
channels.
|
||||
- resistance-cancellation
|
||||
Boolean for all chips other than MAX6581. Set to enable resistance
|
||||
cancellation on remote temperature channel 1.
|
||||
For MAX6581, resistance cancellation enabled for all channels if
|
||||
specified as boolean, otherwise as per bit mask specified.
|
||||
Only supported for remote temperatures (bit 1..7).
|
||||
If not specified, resistance cancellation will be disabled for all
|
||||
channels.
|
||||
- transistor-ideality
|
||||
For MAX6581 only. Two values; first is bit mask, second is ideality
|
||||
select value as per MAX6581 data sheet. Select bit 1..7 for remote
|
||||
channels.
|
||||
Transistor ideality will be initialized to default (1.008) if not
|
||||
specified.
|
||||
|
||||
Example:
|
||||
|
||||
temp-sensor@1a {
|
||||
compatible = "maxim,max6697";
|
||||
reg = <0x1a>;
|
||||
smbus-timeout-disable;
|
||||
resistance-cancellation;
|
||||
alert-mask = <0x72>;
|
||||
over-temperature-mask = <0x7f>;
|
||||
};
|
@@ -66,6 +66,7 @@ Process Processor TjMax(C)
|
||||
i5 3470T 91
|
||||
|
||||
32nm Core i3/i5/i7 Processors
|
||||
i7 2600 98
|
||||
i7 660UM/640/620, 640LM/620, 620M, 610E 105
|
||||
i5 540UM/520/430, 540M/520/450/430 105
|
||||
i3 330E, 370M/350/330 90 rPGA, 105 BGA
|
||||
@@ -79,7 +80,10 @@ Process Processor TjMax(C)
|
||||
P4505/P4500 90
|
||||
|
||||
32nm Atom Processors
|
||||
S1260/1220 95
|
||||
S1240 102
|
||||
Z2460 90
|
||||
Z2760 90
|
||||
D2700/2550/2500 100
|
||||
N2850/2800/2650/2600 100
|
||||
|
||||
@@ -98,6 +102,7 @@ Process Processor TjMax(C)
|
||||
|
||||
45nm Atom Processors
|
||||
D525/510/425/410 100
|
||||
K525/510/425/410 100
|
||||
Z670/650 90
|
||||
Z560/550/540/530P/530/520PT/520/515/510PT/510P 90
|
||||
Z510/500 90
|
||||
@@ -107,7 +112,11 @@ Process Processor TjMax(C)
|
||||
330/230 125
|
||||
E680/660/640/620 90
|
||||
E680T/660T/640T/620T 110
|
||||
E665C/645C 90
|
||||
E665CT/645CT 110
|
||||
CE4170/4150/4110 110
|
||||
CE4200 series unknown
|
||||
CE5300 series unknown
|
||||
|
||||
45nm Core2 Processors
|
||||
Solo ULV SU3500/3300 100
|
||||
|
93
Documentation/hwmon/ina209
Normal file
93
Documentation/hwmon/ina209
Normal file
@@ -0,0 +1,93 @@
|
||||
Kernel driver ina209
|
||||
=====================
|
||||
|
||||
Supported chips:
|
||||
* Burr-Brown / Texas Instruments INA209
|
||||
Prefix: 'ina209'
|
||||
Addresses scanned: -
|
||||
Datasheet:
|
||||
http://www.ti.com/lit/gpn/ina209
|
||||
|
||||
Author: Paul Hays <Paul.Hays@cattail.ca>
|
||||
Author: Ira W. Snyder <iws@ovro.caltech.edu>
|
||||
Author: Guenter Roeck <linux@roeck-us.net>
|
||||
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
The TI / Burr-Brown INA209 monitors voltage, current, and power on the high side
|
||||
of a D.C. power supply. It can perform measurements and calculations in the
|
||||
background to supply readings at any time. It includes a programmable
|
||||
calibration multiplier to scale the displayed current and power values.
|
||||
|
||||
|
||||
Sysfs entries
|
||||
-------------
|
||||
|
||||
The INA209 chip is highly configurable both via hardwiring and via
|
||||
the I2C bus. See the datasheet for details.
|
||||
|
||||
This tries to expose most monitoring features of the hardware via
|
||||
sysfs. It does not support every feature of this chip.
|
||||
|
||||
|
||||
in0_input shunt voltage (mV)
|
||||
in0_input_highest shunt voltage historical maximum reading (mV)
|
||||
in0_input_lowest shunt voltage historical minimum reading (mV)
|
||||
in0_reset_history reset shunt voltage history
|
||||
in0_max shunt voltage max alarm limit (mV)
|
||||
in0_min shunt voltage min alarm limit (mV)
|
||||
in0_crit_max shunt voltage crit max alarm limit (mV)
|
||||
in0_crit_min shunt voltage crit min alarm limit (mV)
|
||||
in0_max_alarm shunt voltage max alarm limit exceeded
|
||||
in0_min_alarm shunt voltage min alarm limit exceeded
|
||||
in0_crit_max_alarm shunt voltage crit max alarm limit exceeded
|
||||
in0_crit_min_alarm shunt voltage crit min alarm limit exceeded
|
||||
|
||||
in1_input bus voltage (mV)
|
||||
in1_input_highest bus voltage historical maximum reading (mV)
|
||||
in1_input_lowest bus voltage historical minimum reading (mV)
|
||||
in1_reset_history reset bus voltage history
|
||||
in1_max bus voltage max alarm limit (mV)
|
||||
in1_min bus voltage min alarm limit (mV)
|
||||
in1_crit_max bus voltage crit max alarm limit (mV)
|
||||
in1_crit_min bus voltage crit min alarm limit (mV)
|
||||
in1_max_alarm bus voltage max alarm limit exceeded
|
||||
in1_min_alarm bus voltage min alarm limit exceeded
|
||||
in1_crit_max_alarm bus voltage crit max alarm limit exceeded
|
||||
in1_crit_min_alarm bus voltage crit min alarm limit exceeded
|
||||
|
||||
power1_input power measurement (uW)
|
||||
power1_input_highest power historical maximum reading (uW)
|
||||
power1_reset_history reset power history
|
||||
power1_max power max alarm limit (uW)
|
||||
power1_crit power crit alarm limit (uW)
|
||||
power1_max_alarm power max alarm limit exceeded
|
||||
power1_crit_alarm power crit alarm limit exceeded
|
||||
|
||||
curr1_input current measurement (mA)
|
||||
|
||||
update_interval data conversion time; affects number of samples used
|
||||
to average results for shunt and bus voltages.
|
||||
|
||||
General Remarks
|
||||
---------------
|
||||
|
||||
The power and current registers in this chip require that the calibration
|
||||
register is programmed correctly before they are used. Normally this is expected
|
||||
to be done in the BIOS. In the absence of BIOS programming, the shunt resistor
|
||||
voltage can be provided using platform data. The driver uses platform data from
|
||||
the ina2xx driver for this purpose. If calibration register data is not provided
|
||||
via platform data, the driver checks if the calibration register has been
|
||||
programmed (ie has a value not equal to zero). If so, this value is retained.
|
||||
Otherwise, a default value reflecting a shunt resistor value of 10 mOhm is
|
||||
programmed into the calibration register.
|
||||
|
||||
|
||||
Output Pins
|
||||
-----------
|
||||
|
||||
Output pin programming is a board feature which depends on the BIOS. It is
|
||||
outside the scope of a hardware monitoring driver to enable or disable output
|
||||
pins.
|
@@ -30,6 +30,14 @@ Supported chips:
|
||||
Prefix: 'it8728'
|
||||
Addresses scanned: from Super I/O config space (8 I/O ports)
|
||||
Datasheet: Not publicly available
|
||||
* IT8771E
|
||||
Prefix: 'it8771'
|
||||
Addresses scanned: from Super I/O config space (8 I/O ports)
|
||||
Datasheet: Not publicly available
|
||||
* IT8772E
|
||||
Prefix: 'it8772'
|
||||
Addresses scanned: from Super I/O config space (8 I/O ports)
|
||||
Datasheet: Not publicly available
|
||||
* IT8782F
|
||||
Prefix: 'it8782'
|
||||
Addresses scanned: from Super I/O config space (8 I/O ports)
|
||||
@@ -83,8 +91,8 @@ Description
|
||||
-----------
|
||||
|
||||
This driver implements support for the IT8705F, IT8712F, IT8716F,
|
||||
IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8758E, IT8781F, IT8782F,
|
||||
IT8783E/F, and SiS950 chips.
|
||||
IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8758E, IT8771E, IT8772E,
|
||||
IT8782F, IT8783E/F, and SiS950 chips.
|
||||
|
||||
These chips are 'Super I/O chips', supporting floppy disks, infrared ports,
|
||||
joysticks and other miscellaneous stuff. For hardware monitoring, they
|
||||
@@ -118,8 +126,8 @@ The IT8726F is just bit enhanced IT8716F with additional hardware
|
||||
for AMD power sequencing. Therefore the chip will appear as IT8716F
|
||||
to userspace applications.
|
||||
|
||||
The IT8728F is considered compatible with the IT8721F, until a datasheet
|
||||
becomes available (hopefully.)
|
||||
The IT8728F, IT8771E, and IT8772E are considered compatible with the IT8721F,
|
||||
until a datasheet becomes available (hopefully.)
|
||||
|
||||
Temperatures are measured in degrees Celsius. An alarm is triggered once
|
||||
when the Overtemperature Shutdown limit is crossed.
|
||||
|
@@ -17,12 +17,13 @@ Supported chips:
|
||||
* Maxim MAX6604
|
||||
Datasheets:
|
||||
http://datasheets.maxim-ic.com/en/ds/MAX6604.pdf
|
||||
* Microchip MCP9804, MCP9805, MCP98242, MCP98243, MCP9843
|
||||
* Microchip MCP9804, MCP9805, MCP98242, MCP98243, MCP98244, MCP9843
|
||||
Datasheets:
|
||||
http://ww1.microchip.com/downloads/en/DeviceDoc/22203C.pdf
|
||||
http://ww1.microchip.com/downloads/en/DeviceDoc/21977b.pdf
|
||||
http://ww1.microchip.com/downloads/en/DeviceDoc/21996a.pdf
|
||||
http://ww1.microchip.com/downloads/en/DeviceDoc/22153c.pdf
|
||||
http://ww1.microchip.com/downloads/en/DeviceDoc/22327A.pdf
|
||||
* NXP Semiconductors SE97, SE97B, SE98, SE98A
|
||||
Datasheets:
|
||||
http://www.nxp.com/documents/data_sheet/SE97.pdf
|
||||
|
90
Documentation/hwmon/lm73
Normal file
90
Documentation/hwmon/lm73
Normal file
@@ -0,0 +1,90 @@
|
||||
Kernel driver lm73
|
||||
==================
|
||||
|
||||
Supported chips:
|
||||
* Texas Instruments LM73
|
||||
Prefix: 'lm73'
|
||||
Addresses scanned: I2C 0x48, 0x49, 0x4a, 0x4c, 0x4d, and 0x4e
|
||||
Datasheet: Publicly available at the Texas Instruments website
|
||||
http://www.ti.com/product/lm73
|
||||
|
||||
Author: Guillaume Ligneul <guillaume.ligneul@gmail.com>
|
||||
Documentation: Chris Verges <kg4ysn@gmail.com>
|
||||
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
The LM73 is a digital temperature sensor. All temperature values are
|
||||
given in degrees Celsius.
|
||||
|
||||
Measurement Resolution Support
|
||||
------------------------------
|
||||
|
||||
The LM73 supports four resolutions, defined in terms of degrees C per
|
||||
LSB: 0.25, 0.125, 0.0625, and 0.3125. Changing the resolution mode
|
||||
affects the conversion time of the LM73's analog-to-digital converter.
|
||||
From userspace, the desired resolution can be specified as a function of
|
||||
conversion time via the 'update_interval' sysfs attribute for the
|
||||
device. This attribute will normalize ranges of input values to the
|
||||
maximum times defined for the resolution in the datasheet.
|
||||
|
||||
Resolution Conv. Time Input Range
|
||||
(C/LSB) (msec) (msec)
|
||||
--------------------------------------
|
||||
0.25 14 0..14
|
||||
0.125 28 15..28
|
||||
0.0625 56 29..56
|
||||
0.03125 112 57..infinity
|
||||
--------------------------------------
|
||||
|
||||
The following examples show how the 'update_interval' attribute can be
|
||||
used to change the conversion time:
|
||||
|
||||
$ echo 0 > update_interval
|
||||
$ cat update_interval
|
||||
14
|
||||
$ cat temp1_input
|
||||
24250
|
||||
|
||||
$ echo 22 > update_interval
|
||||
$ cat update_interval
|
||||
28
|
||||
$ cat temp1_input
|
||||
24125
|
||||
|
||||
$ echo 56 > update_interval
|
||||
$ cat update_interval
|
||||
56
|
||||
$ cat temp1_input
|
||||
24062
|
||||
|
||||
$ echo 85 > update_interval
|
||||
$ cat update_interval
|
||||
112
|
||||
$ cat temp1_input
|
||||
24031
|
||||
|
||||
As shown here, the lm73 driver automatically adjusts any user input for
|
||||
'update_interval' via a step function. Reading back the
|
||||
'update_interval' value after a write operation will confirm the
|
||||
conversion time actively in use.
|
||||
|
||||
Mathematically, the resolution can be derived from the conversion time
|
||||
via the following function:
|
||||
|
||||
g(x) = 0.250 * [log(x/14) / log(2)]
|
||||
|
||||
where 'x' is the output from 'update_interval' and 'g(x)' is the
|
||||
resolution in degrees C per LSB.
|
||||
|
||||
Alarm Support
|
||||
-------------
|
||||
|
||||
The LM73 features a simple over-temperature alarm mechanism. This
|
||||
feature is exposed via the sysfs attributes.
|
||||
|
||||
The attributes 'temp1_max_alarm' and 'temp1_min_alarm' are flags
|
||||
provided by the LM73 that indicate whether the measured temperature has
|
||||
passed the 'temp1_max' and 'temp1_min' thresholds, respectively. These
|
||||
values _must_ be read to clear the registers on the LM73.
|
@@ -16,6 +16,16 @@ Supported chips:
|
||||
Prefixes: 'max34446'
|
||||
Addresses scanned: -
|
||||
Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX34446.pdf
|
||||
* Maxim MAX34460
|
||||
PMBus 12-Channel Voltage Monitor & Sequencer
|
||||
Prefix: 'max34460'
|
||||
Addresses scanned: -
|
||||
Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX34460.pdf
|
||||
* Maxim MAX34461
|
||||
PMBus 16-Channel Voltage Monitor & Sequencer
|
||||
Prefix: 'max34461'
|
||||
Addresses scanned: -
|
||||
Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX34461.pdf
|
||||
|
||||
Author: Guenter Roeck <guenter.roeck@ericsson.com>
|
||||
|
||||
@@ -26,6 +36,9 @@ Description
|
||||
This driver supports hardware montoring for Maxim MAX34440 PMBus 6-Channel
|
||||
Power-Supply Manager, MAX34441 PMBus 5-Channel Power-Supply Manager
|
||||
and Intelligent Fan Controller, and MAX34446 PMBus Power-Supply Data Logger.
|
||||
It also supports the MAX34460 and MAX34461 PMBus Voltage Monitor & Sequencers.
|
||||
The MAX34460 supports 12 voltage channels, and the MAX34461 supports 16 voltage
|
||||
channels.
|
||||
|
||||
The driver is a client driver to the core PMBus driver. Please see
|
||||
Documentation/hwmon/pmbus for details on PMBus client drivers.
|
||||
@@ -109,3 +122,6 @@ temp[1-8]_reset_history Write any value to reset history.
|
||||
|
||||
temp7 and temp8 attributes only exist for MAX34440.
|
||||
MAX34446 only supports temp[1-3].
|
||||
|
||||
MAX34460 supports attribute groups in[1-12] and temp[1-5].
|
||||
MAX34461 supports attribute groups in[1-16] and temp[1-5].
|
||||
|
58
Documentation/hwmon/max6697
Normal file
58
Documentation/hwmon/max6697
Normal file
@@ -0,0 +1,58 @@
|
||||
Kernel driver max6697
|
||||
=====================
|
||||
|
||||
Supported chips:
|
||||
* Maxim MAX6581
|
||||
Prefix: 'max6581'
|
||||
Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX6581.pdf
|
||||
* Maxim MAX6602
|
||||
Prefix: 'max6602'
|
||||
Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX6602.pdf
|
||||
* Maxim MAX6622
|
||||
Prefix: 'max6622'
|
||||
Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX6622.pdf
|
||||
* Maxim MAX6636
|
||||
Prefix: 'max6636'
|
||||
Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX6636.pdf
|
||||
* Maxim MAX6689
|
||||
Prefix: 'max6689'
|
||||
Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX6689.pdf
|
||||
* Maxim MAX6693
|
||||
Prefix: 'max6693'
|
||||
Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX6693.pdf
|
||||
* Maxim MAX6694
|
||||
Prefix: 'max6694'
|
||||
Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX6694.pdf
|
||||
* Maxim MAX6697
|
||||
Prefix: 'max6697'
|
||||
Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX6697.pdf
|
||||
* Maxim MAX6698
|
||||
Prefix: 'max6698'
|
||||
Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX6698.pdf
|
||||
* Maxim MAX6699
|
||||
Prefix: 'max6699'
|
||||
Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX6699.pdf
|
||||
|
||||
Author:
|
||||
Guenter Roeck <linux@roeck-us.net>
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
This driver implements support for several MAX6697 compatible temperature sensor
|
||||
chips. The chips support one local temperature sensor plus four, six, or seven
|
||||
remote temperature sensors. Remote temperature sensors are diode-connected
|
||||
thermal transitors, except for MAX6698 which supports three diode-connected
|
||||
thermal transistors plus three thermistors in addition to the local temperature
|
||||
sensor.
|
||||
|
||||
The driver provides the following sysfs attributes. temp1 is the local (chip)
|
||||
temperature, temp[2..n] are remote temperatures. The actually supported
|
||||
per-channel attributes are chip type and channel dependent.
|
||||
|
||||
tempX_input RO temperature
|
||||
tempX_max RW temperature maximum threshold
|
||||
tempX_max_alarm RO temperature maximum threshold alarm
|
||||
tempX_crit RW temperature critical threshold
|
||||
tempX_crit_alarm RO temperature critical threshold alarm
|
||||
tempX_fault RO temperature diode fault (remote sensors only)
|
@@ -722,14 +722,14 @@ add/subtract if it has been divided before the add/subtract.
|
||||
What to do if a value is found to be invalid, depends on the type of the
|
||||
sysfs attribute that is being set. If it is a continuous setting like a
|
||||
tempX_max or inX_max attribute, then the value should be clamped to its
|
||||
limits using SENSORS_LIMIT(value, min_limit, max_limit). If it is not
|
||||
continuous like for example a tempX_type, then when an invalid value is
|
||||
written, -EINVAL should be returned.
|
||||
limits using clamp_val(value, min_limit, max_limit). If it is not continuous
|
||||
like for example a tempX_type, then when an invalid value is written,
|
||||
-EINVAL should be returned.
|
||||
|
||||
Example1, temp1_max, register is a signed 8 bit value (-128 - 127 degrees):
|
||||
|
||||
long v = simple_strtol(buf, NULL, 10) / 1000;
|
||||
v = SENSORS_LIMIT(v, -128, 127);
|
||||
v = clamp_val(v, -128, 127);
|
||||
/* write v to register */
|
||||
|
||||
Example2, fan divider setting, valid values 2, 4 and 8:
|
||||
|
@@ -121,12 +121,26 @@ in1_max_alarm Input voltage high alarm.
|
||||
in1_lcrit_alarm Input voltage critical low alarm.
|
||||
in1_crit_alarm Input voltage critical high alarm.
|
||||
|
||||
in2_label "vout1"
|
||||
in2_input Measured output voltage.
|
||||
in2_lcrit Critical minimum output Voltage.
|
||||
in2_crit Critical maximum output voltage.
|
||||
in2_lcrit_alarm Critical output voltage critical low alarm.
|
||||
in2_crit_alarm Critical output voltage critical high alarm.
|
||||
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_crit Critical maximum VMON/VDRV voltage.
|
||||
in2_lcrit_alarm VMON/VDRV voltage critical low alarm.
|
||||
in2_crit_alarm VMON/VDRV voltage critical high alarm.
|
||||
|
||||
vmon attributes are supported on ZL2004, ZL9101M,
|
||||
and ZL9117M only.
|
||||
|
||||
inX_label "vout1"
|
||||
inX_input Measured output voltage.
|
||||
inX_lcrit Critical minimum output Voltage.
|
||||
inX_crit Critical maximum output voltage.
|
||||
inX_lcrit_alarm Critical output voltage critical low alarm.
|
||||
inX_crit_alarm Critical output voltage critical high alarm.
|
||||
|
||||
X is 3 for ZL2004, ZL9101M, and ZL9117M, 2 otherwise.
|
||||
|
||||
curr1_label "iout1"
|
||||
curr1_input Measured output current.
|
||||
|
@@ -180,11 +180,11 @@ config SENSORS_ADM9240
|
||||
will be called adm9240.
|
||||
|
||||
config SENSORS_ADT7410
|
||||
tristate "Analog Devices ADT7410"
|
||||
tristate "Analog Devices ADT7410/ADT7420"
|
||||
depends on I2C
|
||||
help
|
||||
If you say yes here you get support for the Analog Devices
|
||||
ADT7410 temperature monitoring chip.
|
||||
ADT7410 and ADT7420 temperature monitoring chips.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called adt7410.
|
||||
@@ -506,7 +506,8 @@ config SENSORS_IT87
|
||||
help
|
||||
If you say yes here you get support for ITE IT8705F, IT8712F,
|
||||
IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8758E,
|
||||
IT8782F, and IT8783E/F sensor chips, and the SiS950 clone.
|
||||
IT8771E, IT8772E, IT8782F, and IT8783E/F sensor chips, and the
|
||||
SiS950 clone.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called it87.
|
||||
@@ -529,8 +530,8 @@ config SENSORS_JC42
|
||||
temperature sensors, which are used on many DDR3 memory modules for
|
||||
mobile devices and servers. Support will include, but not be limited
|
||||
to, ADT7408, AT30TS00, CAT34TS02, CAT6095, MAX6604, MCP9804, MCP9805,
|
||||
MCP98242, MCP98243, MCP9843, SE97, SE98, STTS424(E), STTS2002,
|
||||
STTS3000, TSE2002B3, TSE2002GB2, TS3000B3, and TS3000GB2.
|
||||
MCP98242, MCP98243, MCP98244, MCP9843, SE97, SE98, STTS424(E),
|
||||
STTS2002, STTS3000, TSE2002B3, TSE2002GB2, TS3000B3, and TS3000GB2.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called jc42.
|
||||
@@ -854,6 +855,17 @@ config SENSORS_MAX6650
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called max6650.
|
||||
|
||||
config SENSORS_MAX6697
|
||||
tristate "Maxim MAX6697 and compatibles"
|
||||
depends on I2C
|
||||
help
|
||||
If you say yes here you get support for MAX6581, MAX6602, MAX6622,
|
||||
MAX6636, MAX6689, MAX6693, MAX6694, MAX6697, MAX6698, and MAX6699
|
||||
temperature sensor chips.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called max6697.
|
||||
|
||||
config SENSORS_MCP3021
|
||||
tristate "Microchip MCP3021 and compatibles"
|
||||
depends on I2C
|
||||
@@ -1145,6 +1157,16 @@ config SENSORS_AMC6821
|
||||
This driver can also be build as a module. If so, the module
|
||||
will be called amc6821.
|
||||
|
||||
config SENSORS_INA209
|
||||
tristate "TI / Burr Brown INA209"
|
||||
depends on I2C
|
||||
help
|
||||
If you say yes here you get support for the TI / Burr Brown INA209
|
||||
voltage / current / power monitor I2C interface.
|
||||
|
||||
This driver can also be built as a module. If so, the module will
|
||||
be called ina209.
|
||||
|
||||
config SENSORS_INA2XX
|
||||
tristate "Texas Instruments INA219 and compatibles"
|
||||
depends on I2C
|
||||
|
@@ -65,6 +65,7 @@ obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o
|
||||
obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o
|
||||
obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o
|
||||
obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o
|
||||
obj-$(CONFIG_SENSORS_INA209) += ina209.o
|
||||
obj-$(CONFIG_SENSORS_INA2XX) += ina2xx.o
|
||||
obj-$(CONFIG_SENSORS_IT87) += it87.o
|
||||
obj-$(CONFIG_SENSORS_JC42) += jc42.o
|
||||
@@ -99,6 +100,7 @@ obj-$(CONFIG_SENSORS_MAX197) += max197.o
|
||||
obj-$(CONFIG_SENSORS_MAX6639) += max6639.o
|
||||
obj-$(CONFIG_SENSORS_MAX6642) += max6642.o
|
||||
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_NTC_THERMISTOR) += ntc_thermistor.o
|
||||
|
@@ -137,7 +137,7 @@ static ssize_t set_max_min(struct device *dev,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
temp = SENSORS_LIMIT(temp, -40000, 85000);
|
||||
temp = clamp_val(temp, -40000, 85000);
|
||||
temp = (temp + (temp < 0 ? -500 : 500)) / 1000;
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
|
@@ -193,7 +193,7 @@ static ssize_t set_temp_max(struct device *dev,
|
||||
temp /= 1000;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->temp_max[index] = SENSORS_LIMIT(temp, -128, 127);
|
||||
data->temp_max[index] = clamp_val(temp, -128, 127);
|
||||
if (!read_only)
|
||||
i2c_smbus_write_byte_data(client, ADM1021_REG_TOS_W(index),
|
||||
data->temp_max[index]);
|
||||
@@ -218,7 +218,7 @@ static ssize_t set_temp_min(struct device *dev,
|
||||
temp /= 1000;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->temp_min[index] = SENSORS_LIMIT(temp, -128, 127);
|
||||
data->temp_min[index] = clamp_val(temp, -128, 127);
|
||||
if (!read_only)
|
||||
i2c_smbus_write_byte_data(client, ADM1021_REG_THYST_W(index),
|
||||
data->temp_min[index]);
|
||||
|
@@ -197,7 +197,7 @@ static int adm1026_scaling[] = { /* .001 Volts */
|
||||
};
|
||||
#define NEG12_OFFSET 16000
|
||||
#define SCALE(val, from, to) (((val)*(to) + ((from)/2))/(from))
|
||||
#define INS_TO_REG(n, val) (SENSORS_LIMIT(SCALE(val, adm1026_scaling[n], 192),\
|
||||
#define INS_TO_REG(n, val) (clamp_val(SCALE(val, adm1026_scaling[n], 192),\
|
||||
0, 255))
|
||||
#define INS_FROM_REG(n, val) (SCALE(val, 192, adm1026_scaling[n]))
|
||||
|
||||
@@ -207,7 +207,7 @@ static int adm1026_scaling[] = { /* .001 Volts */
|
||||
* 22500 kHz * 60 (sec/min) * 2 (pulse) / 2 (pulse/rev) == 1350000
|
||||
*/
|
||||
#define FAN_TO_REG(val, div) ((val) <= 0 ? 0xff : \
|
||||
SENSORS_LIMIT(1350000 / ((val) * (div)), \
|
||||
clamp_val(1350000 / ((val) * (div)), \
|
||||
1, 254))
|
||||
#define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : (val) == 0xff ? 0 : \
|
||||
1350000 / ((val) * (div)))
|
||||
@@ -215,14 +215,14 @@ static int adm1026_scaling[] = { /* .001 Volts */
|
||||
#define DIV_TO_REG(val) ((val) >= 8 ? 3 : (val) >= 4 ? 2 : (val) >= 2 ? 1 : 0)
|
||||
|
||||
/* Temperature is reported in 1 degC increments */
|
||||
#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val) + ((val) < 0 ? -500 : 500)) \
|
||||
#define TEMP_TO_REG(val) (clamp_val(((val) + ((val) < 0 ? -500 : 500)) \
|
||||
/ 1000, -127, 127))
|
||||
#define TEMP_FROM_REG(val) ((val) * 1000)
|
||||
#define OFFSET_TO_REG(val) (SENSORS_LIMIT(((val) + ((val) < 0 ? -500 : 500)) \
|
||||
#define OFFSET_TO_REG(val) (clamp_val(((val) + ((val) < 0 ? -500 : 500)) \
|
||||
/ 1000, -127, 127))
|
||||
#define OFFSET_FROM_REG(val) ((val) * 1000)
|
||||
|
||||
#define PWM_TO_REG(val) (SENSORS_LIMIT(val, 0, 255))
|
||||
#define PWM_TO_REG(val) (clamp_val(val, 0, 255))
|
||||
#define PWM_FROM_REG(val) (val)
|
||||
|
||||
#define PWM_MIN_TO_REG(val) ((val) & 0xf0)
|
||||
@@ -233,7 +233,7 @@ static int adm1026_scaling[] = { /* .001 Volts */
|
||||
* indicates that the DAC could be used to drive the fans, but in our
|
||||
* example board (Arima HDAMA) it isn't connected to the fans at all.
|
||||
*/
|
||||
#define DAC_TO_REG(val) (SENSORS_LIMIT(((((val) * 255) + 500) / 2500), 0, 255))
|
||||
#define DAC_TO_REG(val) (clamp_val(((((val) * 255) + 500) / 2500), 0, 255))
|
||||
#define DAC_FROM_REG(val) (((val) * 2500) / 255)
|
||||
|
||||
/*
|
||||
@@ -933,7 +933,7 @@ static void fixup_fan_min(struct device *dev, int fan, int old_div)
|
||||
return;
|
||||
|
||||
new_min = data->fan_min[fan] * old_div / new_div;
|
||||
new_min = SENSORS_LIMIT(new_min, 1, 254);
|
||||
new_min = clamp_val(new_min, 1, 254);
|
||||
data->fan_min[fan] = new_min;
|
||||
adm1026_write_value(client, ADM1026_REG_FAN_MIN(fan), new_min);
|
||||
}
|
||||
@@ -1527,7 +1527,7 @@ static ssize_t set_auto_pwm_min(struct device *dev,
|
||||
return err;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->pwm1.auto_pwm_min = SENSORS_LIMIT(val, 0, 255);
|
||||
data->pwm1.auto_pwm_min = clamp_val(val, 0, 255);
|
||||
if (data->pwm1.enable == 2) { /* apply immediately */
|
||||
data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) |
|
||||
PWM_MIN_TO_REG(data->pwm1.auto_pwm_min));
|
||||
|
@@ -162,13 +162,13 @@ adm1031_write_value(struct i2c_client *client, u8 reg, unsigned int value)
|
||||
static int FAN_TO_REG(int reg, int div)
|
||||
{
|
||||
int tmp;
|
||||
tmp = FAN_FROM_REG(SENSORS_LIMIT(reg, 0, 65535), div);
|
||||
tmp = FAN_FROM_REG(clamp_val(reg, 0, 65535), div);
|
||||
return tmp > 255 ? 255 : tmp;
|
||||
}
|
||||
|
||||
#define FAN_DIV_FROM_REG(reg) (1<<(((reg)&0xc0)>>6))
|
||||
|
||||
#define PWM_TO_REG(val) (SENSORS_LIMIT((val), 0, 255) >> 4)
|
||||
#define PWM_TO_REG(val) (clamp_val((val), 0, 255) >> 4)
|
||||
#define PWM_FROM_REG(val) ((val) << 4)
|
||||
|
||||
#define FAN_CHAN_FROM_REG(reg) (((reg) >> 5) & 7)
|
||||
@@ -675,7 +675,7 @@ static ssize_t set_temp_offset(struct device *dev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val = SENSORS_LIMIT(val, -15000, 15000);
|
||||
val = clamp_val(val, -15000, 15000);
|
||||
mutex_lock(&data->update_lock);
|
||||
data->temp_offset[nr] = TEMP_OFFSET_TO_REG(val);
|
||||
adm1031_write_value(client, ADM1031_REG_TEMP_OFFSET(nr),
|
||||
@@ -696,7 +696,7 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
|
||||
val = clamp_val(val, -55000, nr == 0 ? 127750 : 127875);
|
||||
mutex_lock(&data->update_lock);
|
||||
data->temp_min[nr] = TEMP_TO_REG(val);
|
||||
adm1031_write_value(client, ADM1031_REG_TEMP_MIN(nr),
|
||||
@@ -717,7 +717,7 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
|
||||
val = clamp_val(val, -55000, nr == 0 ? 127750 : 127875);
|
||||
mutex_lock(&data->update_lock);
|
||||
data->temp_max[nr] = TEMP_TO_REG(val);
|
||||
adm1031_write_value(client, ADM1031_REG_TEMP_MAX(nr),
|
||||
@@ -738,7 +738,7 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
|
||||
val = clamp_val(val, -55000, nr == 0 ? 127750 : 127875);
|
||||
mutex_lock(&data->update_lock);
|
||||
data->temp_crit[nr] = TEMP_TO_REG(val);
|
||||
adm1031_write_value(client, ADM1031_REG_TEMP_CRIT(nr),
|
||||
|
@@ -98,13 +98,13 @@ static inline unsigned int IN_FROM_REG(u8 reg, int n)
|
||||
|
||||
static inline u8 IN_TO_REG(unsigned long val, int n)
|
||||
{
|
||||
return SENSORS_LIMIT(SCALE(val, 192, nom_mv[n]), 0, 255);
|
||||
return clamp_val(SCALE(val, 192, nom_mv[n]), 0, 255);
|
||||
}
|
||||
|
||||
/* temperature range: -40..125, 127 disables temperature alarm */
|
||||
static inline s8 TEMP_TO_REG(long val)
|
||||
{
|
||||
return SENSORS_LIMIT(SCALE(val, 1, 1000), -40, 127);
|
||||
return clamp_val(SCALE(val, 1, 1000), -40, 127);
|
||||
}
|
||||
|
||||
/* two fans, each with low fan speed limit */
|
||||
@@ -122,7 +122,7 @@ static inline unsigned int FAN_FROM_REG(u8 reg, u8 div)
|
||||
/* analog out 0..1250mV */
|
||||
static inline u8 AOUT_TO_REG(unsigned long val)
|
||||
{
|
||||
return SENSORS_LIMIT(SCALE(val, 255, 1250), 0, 255);
|
||||
return clamp_val(SCALE(val, 255, 1250), 0, 255);
|
||||
}
|
||||
|
||||
static inline unsigned int AOUT_FROM_REG(u8 reg)
|
||||
|
@@ -163,9 +163,9 @@ static int ads7828_probe(struct i2c_client *client,
|
||||
|
||||
/* Bound Vref with min/max values if it was provided */
|
||||
if (data->vref_mv)
|
||||
data->vref_mv = SENSORS_LIMIT(data->vref_mv,
|
||||
ADS7828_EXT_VREF_MV_MIN,
|
||||
ADS7828_EXT_VREF_MV_MAX);
|
||||
data->vref_mv = clamp_val(data->vref_mv,
|
||||
ADS7828_EXT_VREF_MV_MIN,
|
||||
ADS7828_EXT_VREF_MV_MAX);
|
||||
else
|
||||
data->vref_mv = ADS7828_INT_VREF_MV;
|
||||
|
||||
|
@@ -78,10 +78,6 @@ enum adt7410_type { /* keep sorted in alphabetical order */
|
||||
adt7410,
|
||||
};
|
||||
|
||||
/* Addresses scanned */
|
||||
static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
|
||||
I2C_CLIENT_END };
|
||||
|
||||
static const u8 ADT7410_REG_TEMP[4] = {
|
||||
ADT7410_TEMPERATURE, /* input */
|
||||
ADT7410_T_ALARM_HIGH, /* high */
|
||||
@@ -173,8 +169,8 @@ abort:
|
||||
|
||||
static s16 ADT7410_TEMP_TO_REG(long temp)
|
||||
{
|
||||
return DIV_ROUND_CLOSEST(SENSORS_LIMIT(temp, ADT7410_TEMP_MIN,
|
||||
ADT7410_TEMP_MAX) * 128, 1000);
|
||||
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)
|
||||
@@ -269,9 +265,9 @@ static ssize_t adt7410_set_t_hyst(struct device *dev,
|
||||
return ret;
|
||||
/* convert absolute hysteresis value to a 4 bit delta value */
|
||||
limit = ADT7410_REG_TO_TEMP(data, data->temp[1]);
|
||||
hyst = SENSORS_LIMIT(hyst, ADT7410_TEMP_MIN, ADT7410_TEMP_MAX);
|
||||
data->hyst = SENSORS_LIMIT(DIV_ROUND_CLOSEST(limit - hyst, 1000),
|
||||
0, ADT7410_T_HYST_MASK);
|
||||
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;
|
||||
@@ -364,6 +360,7 @@ static int adt7410_probe(struct i2c_client *client,
|
||||
/*
|
||||
* 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) {
|
||||
@@ -410,11 +407,12 @@ static int adt7410_remove(struct i2c_client *client)
|
||||
|
||||
static const struct i2c_device_id adt7410_ids[] = {
|
||||
{ "adt7410", adt7410, },
|
||||
{ "adt7420", adt7410, },
|
||||
{ /* LIST END */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, adt7410_ids);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int adt7410_suspend(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
@@ -436,10 +434,8 @@ static int adt7410_resume(struct device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops adt7410_dev_pm_ops = {
|
||||
.suspend = adt7410_suspend,
|
||||
.resume = adt7410_resume,
|
||||
};
|
||||
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
|
||||
@@ -454,11 +450,11 @@ static struct i2c_driver adt7410_driver = {
|
||||
.probe = adt7410_probe,
|
||||
.remove = adt7410_remove,
|
||||
.id_table = adt7410_ids,
|
||||
.address_list = normal_i2c,
|
||||
.address_list = I2C_ADDRS(0x48, 0x49, 0x4a, 0x4b),
|
||||
};
|
||||
|
||||
module_i2c_driver(adt7410_driver);
|
||||
|
||||
MODULE_AUTHOR("Hartmut Knaack");
|
||||
MODULE_DESCRIPTION("ADT7410 driver");
|
||||
MODULE_DESCRIPTION("ADT7410/ADT7420 driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@@ -836,7 +836,7 @@ static ssize_t set_temp_min(struct device *dev,
|
||||
return -EINVAL;
|
||||
|
||||
temp = DIV_ROUND_CLOSEST(temp, 1000) + 64;
|
||||
temp = SENSORS_LIMIT(temp, 0, 255);
|
||||
temp = clamp_val(temp, 0, 255);
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
data->temp_min[attr->index] = temp;
|
||||
@@ -874,7 +874,7 @@ static ssize_t set_temp_max(struct device *dev,
|
||||
return -EINVAL;
|
||||
|
||||
temp = DIV_ROUND_CLOSEST(temp, 1000) + 64;
|
||||
temp = SENSORS_LIMIT(temp, 0, 255);
|
||||
temp = clamp_val(temp, 0, 255);
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
data->temp_max[attr->index] = temp;
|
||||
@@ -939,7 +939,7 @@ static ssize_t set_volt_max(struct device *dev,
|
||||
|
||||
temp *= 1000; /* convert mV to uV */
|
||||
temp = DIV_ROUND_CLOSEST(temp, x);
|
||||
temp = SENSORS_LIMIT(temp, 0, 255);
|
||||
temp = clamp_val(temp, 0, 255);
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
data->volt_max[attr->index] = temp;
|
||||
@@ -981,7 +981,7 @@ static ssize_t set_volt_min(struct device *dev,
|
||||
|
||||
temp *= 1000; /* convert mV to uV */
|
||||
temp = DIV_ROUND_CLOSEST(temp, x);
|
||||
temp = SENSORS_LIMIT(temp, 0, 255);
|
||||
temp = clamp_val(temp, 0, 255);
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
data->volt_min[attr->index] = temp;
|
||||
@@ -1071,7 +1071,7 @@ static ssize_t set_fan_min(struct device *dev,
|
||||
|
||||
temp = FAN_RPM_TO_PERIOD(temp);
|
||||
temp >>= 8;
|
||||
temp = SENSORS_LIMIT(temp, 1, 255);
|
||||
temp = clamp_val(temp, 1, 255);
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
data->fan_min[attr->index] = temp;
|
||||
@@ -1149,7 +1149,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
|
||||
if (kstrtol(buf, 10, &temp))
|
||||
return -EINVAL;
|
||||
|
||||
temp = SENSORS_LIMIT(temp, 0, 255);
|
||||
temp = clamp_val(temp, 0, 255);
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
data->pwm[attr->index] = temp;
|
||||
@@ -1179,7 +1179,7 @@ static ssize_t set_pwm_max(struct device *dev,
|
||||
if (kstrtol(buf, 10, &temp))
|
||||
return -EINVAL;
|
||||
|
||||
temp = SENSORS_LIMIT(temp, 0, 255);
|
||||
temp = clamp_val(temp, 0, 255);
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
data->pwm_max = temp;
|
||||
@@ -1211,7 +1211,7 @@ static ssize_t set_pwm_min(struct device *dev,
|
||||
if (kstrtol(buf, 10, &temp))
|
||||
return -EINVAL;
|
||||
|
||||
temp = SENSORS_LIMIT(temp, 0, 255);
|
||||
temp = clamp_val(temp, 0, 255);
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
data->pwm_min[attr->index] = temp;
|
||||
@@ -1246,7 +1246,7 @@ static ssize_t set_pwm_hyst(struct device *dev,
|
||||
return -EINVAL;
|
||||
|
||||
temp = DIV_ROUND_CLOSEST(temp, 1000);
|
||||
temp = SENSORS_LIMIT(temp, 0, 15);
|
||||
temp = clamp_val(temp, 0, 15);
|
||||
|
||||
/* package things up */
|
||||
temp &= ADT7462_PWM_HYST_MASK;
|
||||
@@ -1333,7 +1333,7 @@ static ssize_t set_pwm_tmin(struct device *dev,
|
||||
return -EINVAL;
|
||||
|
||||
temp = DIV_ROUND_CLOSEST(temp, 1000) + 64;
|
||||
temp = SENSORS_LIMIT(temp, 0, 255);
|
||||
temp = clamp_val(temp, 0, 255);
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
data->pwm_tmin[attr->index] = temp;
|
||||
|
@@ -452,7 +452,7 @@ static ssize_t set_auto_update_interval(struct device *dev,
|
||||
if (kstrtol(buf, 10, &temp))
|
||||
return -EINVAL;
|
||||
|
||||
temp = SENSORS_LIMIT(temp, 0, 60000);
|
||||
temp = clamp_val(temp, 0, 60000);
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
data->auto_update_interval = temp;
|
||||
@@ -481,7 +481,7 @@ static ssize_t set_num_temp_sensors(struct device *dev,
|
||||
if (kstrtol(buf, 10, &temp))
|
||||
return -EINVAL;
|
||||
|
||||
temp = SENSORS_LIMIT(temp, -1, 10);
|
||||
temp = clamp_val(temp, -1, 10);
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
data->num_temp_sensors = temp;
|
||||
@@ -515,7 +515,7 @@ static ssize_t set_temp_min(struct device *dev,
|
||||
return -EINVAL;
|
||||
|
||||
temp = DIV_ROUND_CLOSEST(temp, 1000);
|
||||
temp = SENSORS_LIMIT(temp, 0, 255);
|
||||
temp = clamp_val(temp, 0, 255);
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
data->temp_min[attr->index] = temp;
|
||||
@@ -549,7 +549,7 @@ static ssize_t set_temp_max(struct device *dev,
|
||||
return -EINVAL;
|
||||
|
||||
temp = DIV_ROUND_CLOSEST(temp, 1000);
|
||||
temp = SENSORS_LIMIT(temp, 0, 255);
|
||||
temp = clamp_val(temp, 0, 255);
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
data->temp_max[attr->index] = temp;
|
||||
@@ -604,7 +604,7 @@ static ssize_t set_fan_max(struct device *dev,
|
||||
return -EINVAL;
|
||||
|
||||
temp = FAN_RPM_TO_PERIOD(temp);
|
||||
temp = SENSORS_LIMIT(temp, 1, 65534);
|
||||
temp = clamp_val(temp, 1, 65534);
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
data->fan_max[attr->index] = temp;
|
||||
@@ -641,7 +641,7 @@ static ssize_t set_fan_min(struct device *dev,
|
||||
return -EINVAL;
|
||||
|
||||
temp = FAN_RPM_TO_PERIOD(temp);
|
||||
temp = SENSORS_LIMIT(temp, 1, 65534);
|
||||
temp = clamp_val(temp, 1, 65534);
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
data->fan_min[attr->index] = temp;
|
||||
@@ -717,7 +717,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
|
||||
if (kstrtol(buf, 10, &temp))
|
||||
return -EINVAL;
|
||||
|
||||
temp = SENSORS_LIMIT(temp, 0, 255);
|
||||
temp = clamp_val(temp, 0, 255);
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
data->pwm[attr->index] = temp;
|
||||
@@ -749,7 +749,7 @@ static ssize_t set_pwm_max(struct device *dev,
|
||||
if (kstrtol(buf, 10, &temp))
|
||||
return -EINVAL;
|
||||
|
||||
temp = SENSORS_LIMIT(temp, 0, 255);
|
||||
temp = clamp_val(temp, 0, 255);
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
data->pwm_max[attr->index] = temp;
|
||||
@@ -782,7 +782,7 @@ static ssize_t set_pwm_min(struct device *dev,
|
||||
if (kstrtol(buf, 10, &temp))
|
||||
return -EINVAL;
|
||||
|
||||
temp = SENSORS_LIMIT(temp, 0, 255);
|
||||
temp = clamp_val(temp, 0, 255);
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
data->pwm_min[attr->index] = temp;
|
||||
@@ -826,7 +826,7 @@ static ssize_t set_pwm_tmin(struct device *dev,
|
||||
return -EINVAL;
|
||||
|
||||
temp = DIV_ROUND_CLOSEST(temp, 1000);
|
||||
temp = SENSORS_LIMIT(temp, 0, 255);
|
||||
temp = clamp_val(temp, 0, 255);
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
data->pwm_tmin[attr->index] = temp;
|
||||
|
@@ -201,10 +201,10 @@ static inline u16 temp2reg(struct adt7475_data *data, long val)
|
||||
u16 ret;
|
||||
|
||||
if (!(data->config5 & CONFIG5_TWOSCOMP)) {
|
||||
val = SENSORS_LIMIT(val, -64000, 191000);
|
||||
val = clamp_val(val, -64000, 191000);
|
||||
ret = (val + 64500) / 1000;
|
||||
} else {
|
||||
val = SENSORS_LIMIT(val, -128000, 127000);
|
||||
val = clamp_val(val, -128000, 127000);
|
||||
if (val < -500)
|
||||
ret = (256500 + val) / 1000;
|
||||
else
|
||||
@@ -240,7 +240,7 @@ static inline u16 rpm2tach(unsigned long rpm)
|
||||
if (rpm == 0)
|
||||
return 0;
|
||||
|
||||
return SENSORS_LIMIT((90000 * 60) / rpm, 1, 0xFFFF);
|
||||
return clamp_val((90000 * 60) / rpm, 1, 0xFFFF);
|
||||
}
|
||||
|
||||
/* Scaling factors for voltage inputs, taken from the ADT7490 datasheet */
|
||||
@@ -271,7 +271,7 @@ static inline u16 volt2reg(int channel, long volt, u8 bypass_attn)
|
||||
reg = (volt * 1024) / 2250;
|
||||
else
|
||||
reg = (volt * r[1] * 1024) / ((r[0] + r[1]) * 2250);
|
||||
return SENSORS_LIMIT(reg, 0, 1023) & (0xff << 2);
|
||||
return clamp_val(reg, 0, 1023) & (0xff << 2);
|
||||
}
|
||||
|
||||
static u16 adt7475_read_word(struct i2c_client *client, int reg)
|
||||
@@ -451,10 +451,10 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *attr,
|
||||
switch (sattr->nr) {
|
||||
case OFFSET:
|
||||
if (data->config5 & CONFIG5_TEMPOFFSET) {
|
||||
val = SENSORS_LIMIT(val, -63000, 127000);
|
||||
val = clamp_val(val, -63000, 127000);
|
||||
out = data->temp[OFFSET][sattr->index] = val / 1000;
|
||||
} else {
|
||||
val = SENSORS_LIMIT(val, -63000, 64000);
|
||||
val = clamp_val(val, -63000, 64000);
|
||||
out = data->temp[OFFSET][sattr->index] = val / 500;
|
||||
}
|
||||
break;
|
||||
@@ -471,7 +471,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *attr,
|
||||
adt7475_read_hystersis(client);
|
||||
|
||||
temp = reg2temp(data, data->temp[THERM][sattr->index]);
|
||||
val = SENSORS_LIMIT(val, temp - 15000, temp);
|
||||
val = clamp_val(val, temp - 15000, temp);
|
||||
val = (temp - val) / 1000;
|
||||
|
||||
if (sattr->index != 1) {
|
||||
@@ -577,7 +577,7 @@ static ssize_t set_point2(struct device *dev, struct device_attribute *attr,
|
||||
* to figure the range
|
||||
*/
|
||||
temp = reg2temp(data, data->temp[AUTOMIN][sattr->index]);
|
||||
val = SENSORS_LIMIT(val, temp + autorange_table[0],
|
||||
val = clamp_val(val, temp + autorange_table[0],
|
||||
temp + autorange_table[ARRAY_SIZE(autorange_table) - 1]);
|
||||
val -= temp;
|
||||
|
||||
@@ -701,7 +701,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
|
||||
break;
|
||||
}
|
||||
|
||||
data->pwm[sattr->nr][sattr->index] = SENSORS_LIMIT(val, 0, 0xFF);
|
||||
data->pwm[sattr->nr][sattr->index] = clamp_val(val, 0, 0xFF);
|
||||
i2c_smbus_write_byte_data(client, reg,
|
||||
data->pwm[sattr->nr][sattr->index]);
|
||||
|
||||
|
@@ -241,7 +241,7 @@ static ssize_t set_temp(
|
||||
int ret = kstrtol(buf, 10, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
val = SENSORS_LIMIT(val / 1000, -128, 127);
|
||||
val = clamp_val(val / 1000, -128, 127);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->temp[ix] = val;
|
||||
@@ -332,7 +332,7 @@ static ssize_t set_pwm1(
|
||||
return ret;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->pwm1 = SENSORS_LIMIT(val , 0, 255);
|
||||
data->pwm1 = clamp_val(val , 0, 255);
|
||||
i2c_smbus_write_byte_data(client, AMC6821_REG_DCY, data->pwm1);
|
||||
mutex_unlock(&data->update_lock);
|
||||
return count;
|
||||
@@ -499,11 +499,11 @@ static ssize_t set_temp_auto_point_temp(
|
||||
mutex_lock(&data->update_lock);
|
||||
switch (ix) {
|
||||
case 0:
|
||||
ptemp[0] = SENSORS_LIMIT(val / 1000, 0,
|
||||
data->temp1_auto_point_temp[1]);
|
||||
ptemp[0] = SENSORS_LIMIT(ptemp[0], 0,
|
||||
data->temp2_auto_point_temp[1]);
|
||||
ptemp[0] = SENSORS_LIMIT(ptemp[0], 0, 63);
|
||||
ptemp[0] = clamp_val(val / 1000, 0,
|
||||
data->temp1_auto_point_temp[1]);
|
||||
ptemp[0] = clamp_val(ptemp[0], 0,
|
||||
data->temp2_auto_point_temp[1]);
|
||||
ptemp[0] = clamp_val(ptemp[0], 0, 63);
|
||||
if (i2c_smbus_write_byte_data(
|
||||
client,
|
||||
AMC6821_REG_PSV_TEMP,
|
||||
@@ -515,20 +515,12 @@ static ssize_t set_temp_auto_point_temp(
|
||||
goto EXIT;
|
||||
break;
|
||||
case 1:
|
||||
ptemp[1] = SENSORS_LIMIT(
|
||||
val / 1000,
|
||||
(ptemp[0] & 0x7C) + 4,
|
||||
124);
|
||||
ptemp[1] = clamp_val(val / 1000, (ptemp[0] & 0x7C) + 4, 124);
|
||||
ptemp[1] &= 0x7C;
|
||||
ptemp[2] = SENSORS_LIMIT(
|
||||
ptemp[2], ptemp[1] + 1,
|
||||
255);
|
||||
ptemp[2] = clamp_val(ptemp[2], ptemp[1] + 1, 255);
|
||||
break;
|
||||
case 2:
|
||||
ptemp[2] = SENSORS_LIMIT(
|
||||
val / 1000,
|
||||
ptemp[1]+1,
|
||||
255);
|
||||
ptemp[2] = clamp_val(val / 1000, ptemp[1]+1, 255);
|
||||
break;
|
||||
default:
|
||||
dev_dbg(dev, "Unknown attr->index (%d).\n", ix);
|
||||
@@ -561,7 +553,7 @@ static ssize_t set_pwm1_auto_point_pwm(
|
||||
return ret;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->pwm1_auto_point_pwm[1] = SENSORS_LIMIT(val, 0, 254);
|
||||
data->pwm1_auto_point_pwm[1] = clamp_val(val, 0, 254);
|
||||
if (i2c_smbus_write_byte_data(client, AMC6821_REG_DCY_LOW_TEMP,
|
||||
data->pwm1_auto_point_pwm[1])) {
|
||||
dev_err(&client->dev, "Register write error, aborting.\n");
|
||||
@@ -629,7 +621,7 @@ static ssize_t set_fan(
|
||||
val = 1 > val ? 0xFFFF : 6000000/val;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->fan[ix] = (u16) SENSORS_LIMIT(val, 1, 0xFFFF);
|
||||
data->fan[ix] = (u16) clamp_val(val, 1, 0xFFFF);
|
||||
if (i2c_smbus_write_byte_data(client, fan_reg_low[ix],
|
||||
data->fan[ix] & 0xFF)) {
|
||||
dev_err(&client->dev, "Register write error, aborting.\n");
|
||||
|
@@ -114,7 +114,7 @@ static const u16 asb100_reg_temp_hyst[] = {0, 0x3a, 0x153, 0x253, 0x19};
|
||||
*/
|
||||
static u8 IN_TO_REG(unsigned val)
|
||||
{
|
||||
unsigned nval = SENSORS_LIMIT(val, ASB100_IN_MIN, ASB100_IN_MAX);
|
||||
unsigned nval = clamp_val(val, ASB100_IN_MIN, ASB100_IN_MAX);
|
||||
return (nval + 8) / 16;
|
||||
}
|
||||
|
||||
@@ -129,8 +129,8 @@ static u8 FAN_TO_REG(long rpm, int div)
|
||||
return 0;
|
||||
if (rpm == 0)
|
||||
return 255;
|
||||
rpm = SENSORS_LIMIT(rpm, 1, 1000000);
|
||||
return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
|
||||
rpm = clamp_val(rpm, 1, 1000000);
|
||||
return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
|
||||
}
|
||||
|
||||
static int FAN_FROM_REG(u8 val, int div)
|
||||
@@ -148,7 +148,7 @@ static int FAN_FROM_REG(u8 val, int div)
|
||||
*/
|
||||
static u8 TEMP_TO_REG(long temp)
|
||||
{
|
||||
int ntemp = SENSORS_LIMIT(temp, ASB100_TEMP_MIN, ASB100_TEMP_MAX);
|
||||
int ntemp = clamp_val(temp, ASB100_TEMP_MIN, ASB100_TEMP_MAX);
|
||||
ntemp += (ntemp < 0 ? -500 : 500);
|
||||
return (u8)(ntemp / 1000);
|
||||
}
|
||||
@@ -164,7 +164,7 @@ static int TEMP_FROM_REG(u8 reg)
|
||||
*/
|
||||
static u8 ASB100_PWM_TO_REG(int pwm)
|
||||
{
|
||||
pwm = SENSORS_LIMIT(pwm, 0, 255);
|
||||
pwm = clamp_val(pwm, 0, 255);
|
||||
return (u8)(pwm / 16);
|
||||
}
|
||||
|
||||
|
@@ -191,7 +191,7 @@ static ssize_t store_u8(struct device *dev, struct device_attribute *attr,
|
||||
if (kstrtol(buf, 10, &reqval))
|
||||
return -EINVAL;
|
||||
|
||||
reqval = SENSORS_LIMIT(reqval, 0, 255);
|
||||
reqval = clamp_val(reqval, 0, 255);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->reg[param->msb[0]] = reqval;
|
||||
@@ -224,7 +224,7 @@ static ssize_t store_bitmask(struct device *dev,
|
||||
if (kstrtol(buf, 10, &reqval))
|
||||
return -EINVAL;
|
||||
|
||||
reqval = SENSORS_LIMIT(reqval, 0, param->mask[0]);
|
||||
reqval = clamp_val(reqval, 0, param->mask[0]);
|
||||
|
||||
reqval = (reqval & param->mask[0]) << param->shift[0];
|
||||
|
||||
@@ -274,7 +274,7 @@ static ssize_t store_fan16(struct device *dev,
|
||||
* generating an alarm.
|
||||
*/
|
||||
reqval =
|
||||
(reqval <= 0 ? 0xffff : SENSORS_LIMIT(5400000 / reqval, 0, 0xfffe));
|
||||
(reqval <= 0 ? 0xffff : clamp_val(5400000 / reqval, 0, 0xfffe));
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->reg[param->msb[0]] = (reqval >> 8) & 0xff;
|
||||
@@ -343,11 +343,11 @@ static ssize_t store_in8(struct device *dev, struct device_attribute *attr,
|
||||
if (kstrtol(buf, 10, &reqval))
|
||||
return -EINVAL;
|
||||
|
||||
reqval = SENSORS_LIMIT(reqval, 0, 0xffff);
|
||||
reqval = clamp_val(reqval, 0, 0xffff);
|
||||
|
||||
reqval = reqval * 0xc0 / asc7621_in_scaling[nr];
|
||||
|
||||
reqval = SENSORS_LIMIT(reqval, 0, 0xff);
|
||||
reqval = clamp_val(reqval, 0, 0xff);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->reg[param->msb[0]] = reqval;
|
||||
@@ -376,7 +376,7 @@ static ssize_t store_temp8(struct device *dev,
|
||||
if (kstrtol(buf, 10, &reqval))
|
||||
return -EINVAL;
|
||||
|
||||
reqval = SENSORS_LIMIT(reqval, -127000, 127000);
|
||||
reqval = clamp_val(reqval, -127000, 127000);
|
||||
|
||||
temp = reqval / 1000;
|
||||
|
||||
@@ -432,7 +432,7 @@ static ssize_t store_temp62(struct device *dev,
|
||||
if (kstrtol(buf, 10, &reqval))
|
||||
return -EINVAL;
|
||||
|
||||
reqval = SENSORS_LIMIT(reqval, -32000, 31750);
|
||||
reqval = clamp_val(reqval, -32000, 31750);
|
||||
i = reqval / 1000;
|
||||
f = reqval - (i * 1000);
|
||||
temp = i << 2;
|
||||
@@ -468,7 +468,7 @@ static ssize_t show_ap2_temp(struct device *dev,
|
||||
auto_point1 = ((s8) data->reg[param->msb[1]]) * 1000;
|
||||
regval =
|
||||
((data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0]);
|
||||
temp = auto_point1 + asc7621_range_map[SENSORS_LIMIT(regval, 0, 15)];
|
||||
temp = auto_point1 + asc7621_range_map[clamp_val(regval, 0, 15)];
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
return sprintf(buf, "%d\n", temp);
|
||||
@@ -489,7 +489,7 @@ static ssize_t store_ap2_temp(struct device *dev,
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
auto_point1 = data->reg[param->msb[1]] * 1000;
|
||||
reqval = SENSORS_LIMIT(reqval, auto_point1 + 2000, auto_point1 + 80000);
|
||||
reqval = clamp_val(reqval, auto_point1 + 2000, auto_point1 + 80000);
|
||||
|
||||
for (i = ARRAY_SIZE(asc7621_range_map) - 1; i >= 0; i--) {
|
||||
if (reqval >= auto_point1 + asc7621_range_map[i]) {
|
||||
@@ -523,7 +523,7 @@ static ssize_t show_pwm_ac(struct device *dev,
|
||||
regval = config | (altbit << 3);
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
return sprintf(buf, "%u\n", map[SENSORS_LIMIT(regval, 0, 15)]);
|
||||
return sprintf(buf, "%u\n", map[clamp_val(regval, 0, 15)]);
|
||||
}
|
||||
|
||||
static ssize_t store_pwm_ac(struct device *dev,
|
||||
@@ -663,7 +663,7 @@ static ssize_t show_pwm_freq(struct device *dev,
|
||||
u8 regval =
|
||||
(data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0];
|
||||
|
||||
regval = SENSORS_LIMIT(regval, 0, 15);
|
||||
regval = clamp_val(regval, 0, 15);
|
||||
|
||||
return sprintf(buf, "%u\n", asc7621_pwm_freq_map[regval]);
|
||||
}
|
||||
@@ -711,7 +711,7 @@ static ssize_t show_pwm_ast(struct device *dev,
|
||||
u8 regval =
|
||||
(data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0];
|
||||
|
||||
regval = SENSORS_LIMIT(regval, 0, 7);
|
||||
regval = clamp_val(regval, 0, 7);
|
||||
|
||||
return sprintf(buf, "%u\n", asc7621_pwm_auto_spinup_map[regval]);
|
||||
|
||||
@@ -759,7 +759,7 @@ static ssize_t show_temp_st(struct device *dev,
|
||||
SETUP_SHOW_data_param(dev, attr);
|
||||
u8 regval =
|
||||
(data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0];
|
||||
regval = SENSORS_LIMIT(regval, 0, 7);
|
||||
regval = clamp_val(regval, 0, 7);
|
||||
|
||||
return sprintf(buf, "%u\n", asc7621_temp_smoothing_time_map[regval]);
|
||||
}
|
||||
|
@@ -198,7 +198,7 @@ struct tjmax {
|
||||
static const struct tjmax __cpuinitconst tjmax_table[] = {
|
||||
{ "CPU 230", 100000 }, /* Model 0x1c, stepping 2 */
|
||||
{ "CPU 330", 125000 }, /* Model 0x1c, stepping 2 */
|
||||
{ "CPU CE4110", 110000 }, /* Model 0x1c, stepping 10 */
|
||||
{ "CPU CE4110", 110000 }, /* Model 0x1c, stepping 10 Sodaville */
|
||||
{ "CPU CE4150", 110000 }, /* Model 0x1c, stepping 10 */
|
||||
{ "CPU CE4170", 110000 }, /* Model 0x1c, stepping 10 */
|
||||
};
|
||||
@@ -212,7 +212,7 @@ struct tjmax_model {
|
||||
#define ANY 0xff
|
||||
|
||||
static const struct tjmax_model __cpuinitconst tjmax_model_table[] = {
|
||||
{ 0x1c, 10, 100000 }, /* D4xx, N4xx, D5xx, N5xx */
|
||||
{ 0x1c, 10, 100000 }, /* D4xx, K4xx, N4xx, D5xx, K5xx, N5xx */
|
||||
{ 0x1c, ANY, 90000 }, /* Z5xx, N2xx, possibly others
|
||||
* Note: Also matches 230 and 330,
|
||||
* which are covered by tjmax_table
|
||||
@@ -222,6 +222,7 @@ static const struct tjmax_model __cpuinitconst tjmax_model_table[] = {
|
||||
* is undetectable by software
|
||||
*/
|
||||
{ 0x27, ANY, 90000 }, /* Atom Medfield (Z2460) */
|
||||
{ 0x35, ANY, 90000 }, /* Atom Clover Trail/Cloverview (Z2760) */
|
||||
{ 0x36, ANY, 100000 }, /* Atom Cedar Trail/Cedarview (N2xxx, D2xxx) */
|
||||
};
|
||||
|
||||
|
@@ -277,7 +277,7 @@ static inline int IN_FROM_REG(int reg, int nominal, int res)
|
||||
|
||||
static inline int IN_TO_REG(int val, int nominal)
|
||||
{
|
||||
return SENSORS_LIMIT((val * 192 + nominal / 2) / nominal, 0, 255);
|
||||
return clamp_val((val * 192 + nominal / 2) / nominal, 0, 255);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -293,8 +293,7 @@ static inline int TEMP_FROM_REG(int reg, int res)
|
||||
|
||||
static inline int TEMP_TO_REG(int val)
|
||||
{
|
||||
return SENSORS_LIMIT((val < 0 ? val - 500 : val + 500) / 1000,
|
||||
-128, 127);
|
||||
return clamp_val((val < 0 ? val - 500 : val + 500) / 1000, -128, 127);
|
||||
}
|
||||
|
||||
/* Temperature range */
|
||||
@@ -332,7 +331,7 @@ static inline int TEMP_HYST_FROM_REG(int reg, int ix)
|
||||
|
||||
static inline int TEMP_HYST_TO_REG(int val, int ix, int reg)
|
||||
{
|
||||
int hyst = SENSORS_LIMIT((val + 500) / 1000, 0, 15);
|
||||
int hyst = clamp_val((val + 500) / 1000, 0, 15);
|
||||
|
||||
return (ix == 1) ? (reg & 0xf0) | hyst : (reg & 0x0f) | (hyst << 4);
|
||||
}
|
||||
@@ -349,10 +348,10 @@ static inline int FAN_FROM_REG(int reg, int tpc)
|
||||
static inline int FAN_TO_REG(int val, int tpc)
|
||||
{
|
||||
if (tpc) {
|
||||
return SENSORS_LIMIT(val / tpc, 0, 0xffff);
|
||||
return clamp_val(val / tpc, 0, 0xffff);
|
||||
} else {
|
||||
return (val <= 0) ? 0xffff :
|
||||
SENSORS_LIMIT(90000 * 60 / val, 0, 0xfffe);
|
||||
clamp_val(90000 * 60 / val, 0, 0xfffe);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1282,7 +1281,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
|
||||
mutex_lock(&data->update_lock);
|
||||
switch (fn) {
|
||||
case SYS_PWM:
|
||||
data->pwm[ix] = SENSORS_LIMIT(val, 0, 255);
|
||||
data->pwm[ix] = clamp_val(val, 0, 255);
|
||||
dme1737_write(data, DME1737_REG_PWM(ix), data->pwm[ix]);
|
||||
break;
|
||||
case SYS_PWM_FREQ:
|
||||
@@ -1450,7 +1449,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
|
||||
break;
|
||||
case SYS_PWM_AUTO_POINT1_PWM:
|
||||
/* Only valid for pwm[1-3] */
|
||||
data->pwm_min[ix] = SENSORS_LIMIT(val, 0, 255);
|
||||
data->pwm_min[ix] = clamp_val(val, 0, 255);
|
||||
dme1737_write(data, DME1737_REG_PWM_MIN(ix),
|
||||
data->pwm_min[ix]);
|
||||
break;
|
||||
|
@@ -405,7 +405,7 @@ static ssize_t set_fan_target(struct device *dev, struct device_attribute *da,
|
||||
if (rpm_target == 0)
|
||||
data->fan_target = 0x1fff;
|
||||
else
|
||||
data->fan_target = SENSORS_LIMIT(
|
||||
data->fan_target = clamp_val(
|
||||
(FAN_RPM_FACTOR * data->fan_multiplier) / rpm_target,
|
||||
0, 0x1fff);
|
||||
|
||||
|
@@ -220,7 +220,7 @@ static ssize_t set_in(struct device *dev, struct device_attribute *devattr,
|
||||
: EMC6W201_REG_IN_HIGH(nr);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->in[sf][nr] = SENSORS_LIMIT(val, 0, 255);
|
||||
data->in[sf][nr] = clamp_val(val, 0, 255);
|
||||
err = emc6w201_write8(client, reg, data->in[sf][nr]);
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
@@ -257,7 +257,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
|
||||
: EMC6W201_REG_TEMP_HIGH(nr);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->temp[sf][nr] = SENSORS_LIMIT(val, -127, 128);
|
||||
data->temp[sf][nr] = clamp_val(val, -127, 128);
|
||||
err = emc6w201_write8(client, reg, data->temp[sf][nr]);
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
@@ -298,7 +298,7 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *devattr,
|
||||
val = 0xFFFF;
|
||||
} else {
|
||||
val = DIV_ROUND_CLOSEST(5400000U, val);
|
||||
val = SENSORS_LIMIT(val, 0, 0xFFFE);
|
||||
val = clamp_val(val, 0, 0xFFFE);
|
||||
}
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
|
@@ -1350,7 +1350,7 @@ static ssize_t store_fan_full_speed(struct device *dev,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
val = SENSORS_LIMIT(val, 23, 1500000);
|
||||
val = clamp_val(val, 23, 1500000);
|
||||
val = fan_to_reg(val);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
@@ -1438,7 +1438,7 @@ static ssize_t store_in_max(struct device *dev, struct device_attribute
|
||||
return err;
|
||||
|
||||
val /= 8;
|
||||
val = SENSORS_LIMIT(val, 0, 255);
|
||||
val = clamp_val(val, 0, 255);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
f71882fg_write8(data, F71882FG_REG_IN1_HIGH, val);
|
||||
@@ -1542,7 +1542,7 @@ static ssize_t store_temp_max(struct device *dev, struct device_attribute
|
||||
return err;
|
||||
|
||||
val /= 1000;
|
||||
val = SENSORS_LIMIT(val, 0, 255);
|
||||
val = clamp_val(val, 0, 255);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
f71882fg_write8(data, F71882FG_REG_TEMP_HIGH(nr), val);
|
||||
@@ -1589,8 +1589,7 @@ static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute
|
||||
|
||||
/* convert abs to relative and check */
|
||||
data->temp_high[nr] = f71882fg_read8(data, F71882FG_REG_TEMP_HIGH(nr));
|
||||
val = SENSORS_LIMIT(val, data->temp_high[nr] - 15,
|
||||
data->temp_high[nr]);
|
||||
val = clamp_val(val, data->temp_high[nr] - 15, data->temp_high[nr]);
|
||||
val = data->temp_high[nr] - val;
|
||||
|
||||
/* convert value to register contents */
|
||||
@@ -1627,7 +1626,7 @@ static ssize_t store_temp_crit(struct device *dev, struct device_attribute
|
||||
return err;
|
||||
|
||||
val /= 1000;
|
||||
val = SENSORS_LIMIT(val, 0, 255);
|
||||
val = clamp_val(val, 0, 255);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
f71882fg_write8(data, F71882FG_REG_TEMP_OVT(nr), val);
|
||||
@@ -1754,7 +1753,7 @@ static ssize_t store_pwm(struct device *dev,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
val = SENSORS_LIMIT(val, 0, 255);
|
||||
val = clamp_val(val, 0, 255);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
|
||||
@@ -1805,7 +1804,7 @@ static ssize_t store_simple_pwm(struct device *dev,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
val = SENSORS_LIMIT(val, 0, 255);
|
||||
val = clamp_val(val, 0, 255);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
f71882fg_write8(data, F71882FG_REG_PWM(nr), val);
|
||||
@@ -1932,7 +1931,7 @@ static ssize_t store_pwm_auto_point_pwm(struct device *dev,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
val = SENSORS_LIMIT(val, 0, 255);
|
||||
val = clamp_val(val, 0, 255);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
|
||||
@@ -1991,8 +1990,8 @@ static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev,
|
||||
mutex_lock(&data->update_lock);
|
||||
data->pwm_auto_point_temp[nr][point] =
|
||||
f71882fg_read8(data, F71882FG_REG_POINT_TEMP(nr, point));
|
||||
val = SENSORS_LIMIT(val, data->pwm_auto_point_temp[nr][point] - 15,
|
||||
data->pwm_auto_point_temp[nr][point]);
|
||||
val = clamp_val(val, data->pwm_auto_point_temp[nr][point] - 15,
|
||||
data->pwm_auto_point_temp[nr][point]);
|
||||
val = data->pwm_auto_point_temp[nr][point] - val;
|
||||
|
||||
reg = f71882fg_read8(data, F71882FG_REG_FAN_HYST(nr / 2));
|
||||
@@ -2126,9 +2125,9 @@ static ssize_t store_pwm_auto_point_temp(struct device *dev,
|
||||
val /= 1000;
|
||||
|
||||
if (data->auto_point_temp_signed)
|
||||
val = SENSORS_LIMIT(val, -128, 127);
|
||||
val = clamp_val(val, -128, 127);
|
||||
else
|
||||
val = SENSORS_LIMIT(val, 0, 127);
|
||||
val = clamp_val(val, 0, 127);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
f71882fg_write8(data, F71882FG_REG_POINT_TEMP(pwm, point), val);
|
||||
|
@@ -359,7 +359,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->pwm[nr] = SENSORS_LIMIT(val, 0, 255);
|
||||
data->pwm[nr] = clamp_val(val, 0, 255);
|
||||
f75375_write_pwm(client, nr);
|
||||
mutex_unlock(&data->update_lock);
|
||||
return count;
|
||||
@@ -556,7 +556,7 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
val = SENSORS_LIMIT(VOLT_TO_REG(val), 0, 0xff);
|
||||
val = clamp_val(VOLT_TO_REG(val), 0, 0xff);
|
||||
mutex_lock(&data->update_lock);
|
||||
data->in_max[nr] = val;
|
||||
f75375_write8(client, F75375_REG_VOLT_HIGH(nr), data->in_max[nr]);
|
||||
@@ -577,7 +577,7 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
val = SENSORS_LIMIT(VOLT_TO_REG(val), 0, 0xff);
|
||||
val = clamp_val(VOLT_TO_REG(val), 0, 0xff);
|
||||
mutex_lock(&data->update_lock);
|
||||
data->in_min[nr] = val;
|
||||
f75375_write8(client, F75375_REG_VOLT_LOW(nr), data->in_min[nr]);
|
||||
@@ -625,7 +625,7 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
val = SENSORS_LIMIT(TEMP_TO_REG(val), 0, 127);
|
||||
val = clamp_val(TEMP_TO_REG(val), 0, 127);
|
||||
mutex_lock(&data->update_lock);
|
||||
data->temp_high[nr] = val;
|
||||
f75375_write8(client, F75375_REG_TEMP_HIGH(nr), data->temp_high[nr]);
|
||||
@@ -646,7 +646,7 @@ static ssize_t set_temp_max_hyst(struct device *dev,
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
val = SENSORS_LIMIT(TEMP_TO_REG(val), 0, 127);
|
||||
val = clamp_val(TEMP_TO_REG(val), 0, 127);
|
||||
mutex_lock(&data->update_lock);
|
||||
data->temp_max_hyst[nr] = val;
|
||||
f75375_write8(client, F75375_REG_TEMP_HYST(nr),
|
||||
@@ -822,7 +822,7 @@ static void f75375_init(struct i2c_client *client, struct f75375_data *data,
|
||||
if (auto_mode_enabled(f75375s_pdata->pwm_enable[nr]) ||
|
||||
!duty_mode_enabled(f75375s_pdata->pwm_enable[nr]))
|
||||
continue;
|
||||
data->pwm[nr] = SENSORS_LIMIT(f75375s_pdata->pwm[nr], 0, 255);
|
||||
data->pwm[nr] = clamp_val(f75375s_pdata->pwm[nr], 0, 255);
|
||||
f75375_write_pwm(client, nr);
|
||||
}
|
||||
|
||||
|
@@ -379,7 +379,7 @@ static ssize_t store_temp_max(struct device *dev, struct device_attribute
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
v = SENSORS_LIMIT(v / 1000, -128, 127) + 128;
|
||||
v = clamp_val(v / 1000, -128, 127) + 128;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
i2c_smbus_write_byte_data(to_i2c_client(dev),
|
||||
@@ -540,7 +540,7 @@ static ssize_t store_pwm_auto_point1_pwm(struct device *dev,
|
||||
|
||||
/* reg: 0 = allow turning off (except on the syl), 1-255 = 50-100% */
|
||||
if (v || data->kind == fscsyl) {
|
||||
v = SENSORS_LIMIT(v, 128, 255);
|
||||
v = clamp_val(v, 128, 255);
|
||||
v = (v - 128) * 2 + 1;
|
||||
}
|
||||
|
||||
|
@@ -171,7 +171,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *da,
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->set_cnt = PWM_TO_CNT(SENSORS_LIMIT(val, 0, 255));
|
||||
data->set_cnt = PWM_TO_CNT(clamp_val(val, 0, 255));
|
||||
g760a_write_value(client, G760A_REG_SET_CNT, data->set_cnt);
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
|
@@ -86,7 +86,7 @@ enum chips { gl518sm_r00, gl518sm_r80 };
|
||||
#define BOOL_FROM_REG(val) ((val) ? 0 : 1)
|
||||
#define BOOL_TO_REG(val) ((val) ? 0 : 1)
|
||||
|
||||
#define TEMP_TO_REG(val) SENSORS_LIMIT(((((val) < 0 ? \
|
||||
#define TEMP_TO_REG(val) clamp_val(((((val) < 0 ? \
|
||||
(val) - 500 : \
|
||||
(val) + 500) / 1000) + 119), 0, 255)
|
||||
#define TEMP_FROM_REG(val) (((val) - 119) * 1000)
|
||||
@@ -96,15 +96,15 @@ static inline u8 FAN_TO_REG(long rpm, int div)
|
||||
long rpmdiv;
|
||||
if (rpm == 0)
|
||||
return 0;
|
||||
rpmdiv = SENSORS_LIMIT(rpm, 1, 960000) * div;
|
||||
return SENSORS_LIMIT((480000 + rpmdiv / 2) / rpmdiv, 1, 255);
|
||||
rpmdiv = clamp_val(rpm, 1, 960000) * div;
|
||||
return clamp_val((480000 + rpmdiv / 2) / rpmdiv, 1, 255);
|
||||
}
|
||||
#define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : (480000 / ((val) * (div))))
|
||||
|
||||
#define IN_TO_REG(val) SENSORS_LIMIT((((val) + 9) / 19), 0, 255)
|
||||
#define IN_TO_REG(val) clamp_val((((val) + 9) / 19), 0, 255)
|
||||
#define IN_FROM_REG(val) ((val) * 19)
|
||||
|
||||
#define VDD_TO_REG(val) SENSORS_LIMIT((((val) * 4 + 47) / 95), 0, 255)
|
||||
#define VDD_TO_REG(val) clamp_val((((val) * 4 + 47) / 95), 0, 255)
|
||||
#define VDD_FROM_REG(val) (((val) * 95 + 2) / 4)
|
||||
|
||||
#define DIV_FROM_REG(val) (1 << (val))
|
||||
|
@@ -144,10 +144,10 @@ static ssize_t get_cpu_vid(struct device *dev, struct device_attribute *attr,
|
||||
static DEVICE_ATTR(cpu0_vid, S_IRUGO, get_cpu_vid, NULL);
|
||||
|
||||
#define VDD_FROM_REG(val) (((val) * 95 + 2) / 4)
|
||||
#define VDD_TO_REG(val) SENSORS_LIMIT((((val) * 4 + 47) / 95), 0, 255)
|
||||
#define VDD_TO_REG(val) clamp_val((((val) * 4 + 47) / 95), 0, 255)
|
||||
|
||||
#define IN_FROM_REG(val) ((val) * 19)
|
||||
#define IN_TO_REG(val) SENSORS_LIMIT((((val) + 9) / 19), 0, 255)
|
||||
#define IN_TO_REG(val) clamp_val((((val) + 9) / 19), 0, 255)
|
||||
|
||||
static ssize_t get_in_input(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
@@ -285,8 +285,7 @@ static SENSOR_DEVICE_ATTR(in4_max, S_IRUGO | S_IWUSR,
|
||||
#define DIV_FROM_REG(val) (1 << (val))
|
||||
#define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : (480000 / ((val) << (div))))
|
||||
#define FAN_TO_REG(val, div) ((val) <= 0 ? 0 : \
|
||||
SENSORS_LIMIT((480000 + ((val) << ((div)-1))) / ((val) << (div)), 1, \
|
||||
255))
|
||||
clamp_val((480000 + ((val) << ((div)-1))) / ((val) << (div)), 1, 255))
|
||||
|
||||
static ssize_t get_fan_input(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
@@ -450,7 +449,7 @@ static DEVICE_ATTR(fan1_off, S_IRUGO | S_IWUSR,
|
||||
get_fan_off, set_fan_off);
|
||||
|
||||
#define TEMP_FROM_REG(val) (((val) - 130) * 1000)
|
||||
#define TEMP_TO_REG(val) SENSORS_LIMIT(((((val) < 0 ? \
|
||||
#define TEMP_TO_REG(val) clamp_val(((((val) < 0 ? \
|
||||
(val) - 500 : (val) + 500) / 1000) + 130), 0, 255)
|
||||
|
||||
static ssize_t get_temp_input(struct device *dev, struct device_attribute *attr,
|
||||
|
636
drivers/hwmon/ina209.c
Normal file
636
drivers/hwmon/ina209.c
Normal file
@@ -0,0 +1,636 @@
|
||||
/*
|
||||
* Driver for the Texas Instruments / Burr Brown INA209
|
||||
* Bidirectional Current/Power Monitor
|
||||
*
|
||||
* Copyright (C) 2012 Guenter Roeck <linux@roeck-us.net>
|
||||
*
|
||||
* Derived from Ira W. Snyder's original driver submission
|
||||
* Copyright (C) 2008 Paul Hays <Paul.Hays@cattail.ca>
|
||||
* Copyright (C) 2008-2009 Ira W. Snyder <iws@ovro.caltech.edu>
|
||||
*
|
||||
* Aligned with ina2xx driver
|
||||
* Copyright (C) 2012 Lothar Felten <l-felten@ti.com>
|
||||
* Thanks to Jan Volkering
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* Datasheet:
|
||||
* http://www.ti.com/lit/gpn/ina209
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
|
||||
#include <linux/platform_data/ina2xx.h>
|
||||
|
||||
/* register definitions */
|
||||
#define INA209_CONFIGURATION 0x00
|
||||
#define INA209_STATUS 0x01
|
||||
#define INA209_STATUS_MASK 0x02
|
||||
#define INA209_SHUNT_VOLTAGE 0x03
|
||||
#define INA209_BUS_VOLTAGE 0x04
|
||||
#define INA209_POWER 0x05
|
||||
#define INA209_CURRENT 0x06
|
||||
#define INA209_SHUNT_VOLTAGE_POS_PEAK 0x07
|
||||
#define INA209_SHUNT_VOLTAGE_NEG_PEAK 0x08
|
||||
#define INA209_BUS_VOLTAGE_MAX_PEAK 0x09
|
||||
#define INA209_BUS_VOLTAGE_MIN_PEAK 0x0a
|
||||
#define INA209_POWER_PEAK 0x0b
|
||||
#define INA209_SHUNT_VOLTAGE_POS_WARN 0x0c
|
||||
#define INA209_SHUNT_VOLTAGE_NEG_WARN 0x0d
|
||||
#define INA209_POWER_WARN 0x0e
|
||||
#define INA209_BUS_VOLTAGE_OVER_WARN 0x0f
|
||||
#define INA209_BUS_VOLTAGE_UNDER_WARN 0x10
|
||||
#define INA209_POWER_OVER_LIMIT 0x11
|
||||
#define INA209_BUS_VOLTAGE_OVER_LIMIT 0x12
|
||||
#define INA209_BUS_VOLTAGE_UNDER_LIMIT 0x13
|
||||
#define INA209_CRITICAL_DAC_POS 0x14
|
||||
#define INA209_CRITICAL_DAC_NEG 0x15
|
||||
#define INA209_CALIBRATION 0x16
|
||||
|
||||
#define INA209_REGISTERS 0x17
|
||||
|
||||
#define INA209_CONFIG_DEFAULT 0x3c47 /* PGA=8, full range */
|
||||
#define INA209_SHUNT_DEFAULT 10000 /* uOhm */
|
||||
|
||||
struct ina209_data {
|
||||
struct device *hwmon_dev;
|
||||
|
||||
struct mutex update_lock;
|
||||
bool valid;
|
||||
unsigned long last_updated; /* in jiffies */
|
||||
|
||||
u16 regs[INA209_REGISTERS]; /* All chip registers */
|
||||
|
||||
u16 config_orig; /* Original configuration */
|
||||
u16 calibration_orig; /* Original calibration */
|
||||
u16 update_interval;
|
||||
};
|
||||
|
||||
static struct ina209_data *ina209_update_device(struct device *dev)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct ina209_data *data = i2c_get_clientdata(client);
|
||||
struct ina209_data *ret = data;
|
||||
s32 val;
|
||||
int i;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
|
||||
if (!data->valid ||
|
||||
time_after(jiffies, data->last_updated + data->update_interval)) {
|
||||
for (i = 0; i < ARRAY_SIZE(data->regs); i++) {
|
||||
val = i2c_smbus_read_word_swapped(client, i);
|
||||
if (val < 0) {
|
||||
ret = ERR_PTR(val);
|
||||
goto abort;
|
||||
}
|
||||
data->regs[i] = val;
|
||||
}
|
||||
data->last_updated = jiffies;
|
||||
data->valid = true;
|
||||
}
|
||||
abort:
|
||||
mutex_unlock(&data->update_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a value from a device register and convert it to the
|
||||
* appropriate sysfs units
|
||||
*/
|
||||
static long ina209_from_reg(const u8 reg, const u16 val)
|
||||
{
|
||||
switch (reg) {
|
||||
case INA209_SHUNT_VOLTAGE:
|
||||
case INA209_SHUNT_VOLTAGE_POS_PEAK:
|
||||
case INA209_SHUNT_VOLTAGE_NEG_PEAK:
|
||||
case INA209_SHUNT_VOLTAGE_POS_WARN:
|
||||
case INA209_SHUNT_VOLTAGE_NEG_WARN:
|
||||
/* LSB=10 uV. Convert to mV. */
|
||||
return DIV_ROUND_CLOSEST(val, 100);
|
||||
|
||||
case INA209_BUS_VOLTAGE:
|
||||
case INA209_BUS_VOLTAGE_MAX_PEAK:
|
||||
case INA209_BUS_VOLTAGE_MIN_PEAK:
|
||||
case INA209_BUS_VOLTAGE_OVER_WARN:
|
||||
case INA209_BUS_VOLTAGE_UNDER_WARN:
|
||||
case INA209_BUS_VOLTAGE_OVER_LIMIT:
|
||||
case INA209_BUS_VOLTAGE_UNDER_LIMIT:
|
||||
/* LSB=4 mV, last 3 bits unused */
|
||||
return (val >> 3) * 4;
|
||||
|
||||
case INA209_CRITICAL_DAC_POS:
|
||||
/* LSB=1 mV, in the upper 8 bits */
|
||||
return val >> 8;
|
||||
|
||||
case INA209_CRITICAL_DAC_NEG:
|
||||
/* LSB=1 mV, in the upper 8 bits */
|
||||
return -1 * (val >> 8);
|
||||
|
||||
case INA209_POWER:
|
||||
case INA209_POWER_PEAK:
|
||||
case INA209_POWER_WARN:
|
||||
case INA209_POWER_OVER_LIMIT:
|
||||
/* LSB=20 mW. Convert to uW */
|
||||
return val * 20 * 1000L;
|
||||
|
||||
case INA209_CURRENT:
|
||||
/* LSB=1 mA (selected). Is in mA */
|
||||
return val;
|
||||
}
|
||||
|
||||
/* programmer goofed */
|
||||
WARN_ON_ONCE(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Take a value and convert it to register format, clamping the value
|
||||
* to the appropriate range.
|
||||
*/
|
||||
static int ina209_to_reg(u8 reg, u16 old, long val)
|
||||
{
|
||||
switch (reg) {
|
||||
case INA209_SHUNT_VOLTAGE_POS_WARN:
|
||||
case INA209_SHUNT_VOLTAGE_NEG_WARN:
|
||||
/* Limit to +- 320 mV, 10 uV LSB */
|
||||
return clamp_val(val, -320, 320) * 100;
|
||||
|
||||
case INA209_BUS_VOLTAGE_OVER_WARN:
|
||||
case INA209_BUS_VOLTAGE_UNDER_WARN:
|
||||
case INA209_BUS_VOLTAGE_OVER_LIMIT:
|
||||
case INA209_BUS_VOLTAGE_UNDER_LIMIT:
|
||||
/*
|
||||
* Limit to 0-32000 mV, 4 mV LSB
|
||||
*
|
||||
* The last three bits aren't part of the value, but we'll
|
||||
* preserve them in their original state.
|
||||
*/
|
||||
return (DIV_ROUND_CLOSEST(clamp_val(val, 0, 32000), 4) << 3)
|
||||
| (old & 0x7);
|
||||
|
||||
case INA209_CRITICAL_DAC_NEG:
|
||||
/*
|
||||
* Limit to -255-0 mV, 1 mV LSB
|
||||
* Convert the value to a positive value for the register
|
||||
*
|
||||
* The value lives in the top 8 bits only, be careful
|
||||
* and keep original value of other bits.
|
||||
*/
|
||||
return (clamp_val(-val, 0, 255) << 8) | (old & 0xff);
|
||||
|
||||
case INA209_CRITICAL_DAC_POS:
|
||||
/*
|
||||
* Limit to 0-255 mV, 1 mV LSB
|
||||
*
|
||||
* The value lives in the top 8 bits only, be careful
|
||||
* and keep original value of other bits.
|
||||
*/
|
||||
return (clamp_val(val, 0, 255) << 8) | (old & 0xff);
|
||||
|
||||
case INA209_POWER_WARN:
|
||||
case INA209_POWER_OVER_LIMIT:
|
||||
/* 20 mW LSB */
|
||||
return DIV_ROUND_CLOSEST(val, 20 * 1000);
|
||||
}
|
||||
|
||||
/* Other registers are read-only, return access error */
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
static int ina209_interval_from_reg(u16 reg)
|
||||
{
|
||||
return 68 >> (15 - ((reg >> 3) & 0x0f));
|
||||
}
|
||||
|
||||
static u16 ina209_reg_from_interval(u16 config, long interval)
|
||||
{
|
||||
int i, adc;
|
||||
|
||||
if (interval <= 0) {
|
||||
adc = 8;
|
||||
} else {
|
||||
adc = 15;
|
||||
for (i = 34 + 34 / 2; i; i >>= 1) {
|
||||
if (i < interval)
|
||||
break;
|
||||
adc--;
|
||||
}
|
||||
}
|
||||
return (config & 0xf807) | (adc << 3) | (adc << 7);
|
||||
}
|
||||
|
||||
static ssize_t ina209_set_interval(struct device *dev,
|
||||
struct device_attribute *da,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct ina209_data *data = ina209_update_device(dev);
|
||||
long val;
|
||||
u16 regval;
|
||||
int ret;
|
||||
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
ret = kstrtol(buf, 10, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
regval = ina209_reg_from_interval(data->regs[INA209_CONFIGURATION],
|
||||
val);
|
||||
i2c_smbus_write_word_swapped(client, INA209_CONFIGURATION, regval);
|
||||
data->regs[INA209_CONFIGURATION] = regval;
|
||||
data->update_interval = ina209_interval_from_reg(regval);
|
||||
mutex_unlock(&data->update_lock);
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ina209_show_interval(struct device *dev,
|
||||
struct device_attribute *da, char *buf)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct ina209_data *data = i2c_get_clientdata(client);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", data->update_interval);
|
||||
}
|
||||
|
||||
/*
|
||||
* History is reset by writing 1 into bit 0 of the respective peak register.
|
||||
* Since more than one peak register may be affected by the scope of a
|
||||
* reset_history attribute write, use a bit mask in attr->index to identify
|
||||
* which registers are affected.
|
||||
*/
|
||||
static u16 ina209_reset_history_regs[] = {
|
||||
INA209_SHUNT_VOLTAGE_POS_PEAK,
|
||||
INA209_SHUNT_VOLTAGE_NEG_PEAK,
|
||||
INA209_BUS_VOLTAGE_MAX_PEAK,
|
||||
INA209_BUS_VOLTAGE_MIN_PEAK,
|
||||
INA209_POWER_PEAK
|
||||
};
|
||||
|
||||
static ssize_t ina209_reset_history(struct device *dev,
|
||||
struct device_attribute *da,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct ina209_data *data = i2c_get_clientdata(client);
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
u32 mask = attr->index;
|
||||
long val;
|
||||
int i, ret;
|
||||
|
||||
ret = kstrtol(buf, 10, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
for (i = 0; i < ARRAY_SIZE(ina209_reset_history_regs); i++) {
|
||||
if (mask & (1 << i))
|
||||
i2c_smbus_write_word_swapped(client,
|
||||
ina209_reset_history_regs[i], 1);
|
||||
}
|
||||
data->valid = false;
|
||||
mutex_unlock(&data->update_lock);
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ina209_set_value(struct device *dev,
|
||||
struct device_attribute *da,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct ina209_data *data = ina209_update_device(dev);
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
int reg = attr->index;
|
||||
long val;
|
||||
int ret;
|
||||
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
ret = kstrtol(buf, 10, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
ret = ina209_to_reg(reg, data->regs[reg], val);
|
||||
if (ret < 0) {
|
||||
count = ret;
|
||||
goto abort;
|
||||
}
|
||||
i2c_smbus_write_word_swapped(client, reg, ret);
|
||||
data->regs[reg] = ret;
|
||||
abort:
|
||||
mutex_unlock(&data->update_lock);
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ina209_show_value(struct device *dev,
|
||||
struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct ina209_data *data = ina209_update_device(dev);
|
||||
long val;
|
||||
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
val = ina209_from_reg(attr->index, data->regs[attr->index]);
|
||||
return snprintf(buf, PAGE_SIZE, "%ld\n", val);
|
||||
}
|
||||
|
||||
static ssize_t ina209_show_alarm(struct device *dev,
|
||||
struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct ina209_data *data = ina209_update_device(dev);
|
||||
const unsigned int mask = attr->index;
|
||||
u16 status;
|
||||
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
status = data->regs[INA209_STATUS];
|
||||
|
||||
/*
|
||||
* All alarms are in the INA209_STATUS register. To avoid a long
|
||||
* switch statement, the mask is passed in attr->index
|
||||
*/
|
||||
return snprintf(buf, PAGE_SIZE, "%u\n", !!(status & mask));
|
||||
}
|
||||
|
||||
/* Shunt voltage, history, limits, alarms */
|
||||
static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, ina209_show_value, NULL,
|
||||
INA209_SHUNT_VOLTAGE);
|
||||
static SENSOR_DEVICE_ATTR(in0_input_highest, S_IRUGO, ina209_show_value, NULL,
|
||||
INA209_SHUNT_VOLTAGE_POS_PEAK);
|
||||
static SENSOR_DEVICE_ATTR(in0_input_lowest, S_IRUGO, ina209_show_value, NULL,
|
||||
INA209_SHUNT_VOLTAGE_NEG_PEAK);
|
||||
static SENSOR_DEVICE_ATTR(in0_reset_history, S_IWUSR, NULL,
|
||||
ina209_reset_history, (1 << 0) | (1 << 1));
|
||||
static SENSOR_DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR, ina209_show_value,
|
||||
ina209_set_value, INA209_SHUNT_VOLTAGE_POS_WARN);
|
||||
static SENSOR_DEVICE_ATTR(in0_min, S_IRUGO | S_IWUSR, ina209_show_value,
|
||||
ina209_set_value, INA209_SHUNT_VOLTAGE_NEG_WARN);
|
||||
static SENSOR_DEVICE_ATTR(in0_crit_max, S_IRUGO | S_IWUSR, ina209_show_value,
|
||||
ina209_set_value, INA209_CRITICAL_DAC_POS);
|
||||
static SENSOR_DEVICE_ATTR(in0_crit_min, S_IRUGO | S_IWUSR, ina209_show_value,
|
||||
ina209_set_value, INA209_CRITICAL_DAC_NEG);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(in0_min_alarm, S_IRUGO, ina209_show_alarm, NULL,
|
||||
1 << 11);
|
||||
static SENSOR_DEVICE_ATTR(in0_max_alarm, S_IRUGO, ina209_show_alarm, NULL,
|
||||
1 << 12);
|
||||
static SENSOR_DEVICE_ATTR(in0_crit_min_alarm, S_IRUGO, ina209_show_alarm, NULL,
|
||||
1 << 6);
|
||||
static SENSOR_DEVICE_ATTR(in0_crit_max_alarm, S_IRUGO, ina209_show_alarm, NULL,
|
||||
1 << 7);
|
||||
|
||||
/* Bus voltage, history, limits, alarms */
|
||||
static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ina209_show_value, NULL,
|
||||
INA209_BUS_VOLTAGE);
|
||||
static SENSOR_DEVICE_ATTR(in1_input_highest, S_IRUGO, ina209_show_value, NULL,
|
||||
INA209_BUS_VOLTAGE_MAX_PEAK);
|
||||
static SENSOR_DEVICE_ATTR(in1_input_lowest, S_IRUGO, ina209_show_value, NULL,
|
||||
INA209_BUS_VOLTAGE_MIN_PEAK);
|
||||
static SENSOR_DEVICE_ATTR(in1_reset_history, S_IWUSR, NULL,
|
||||
ina209_reset_history, (1 << 2) | (1 << 3));
|
||||
static SENSOR_DEVICE_ATTR(in1_max, S_IRUGO | S_IWUSR, ina209_show_value,
|
||||
ina209_set_value, INA209_BUS_VOLTAGE_OVER_WARN);
|
||||
static SENSOR_DEVICE_ATTR(in1_min, S_IRUGO | S_IWUSR, ina209_show_value,
|
||||
ina209_set_value, INA209_BUS_VOLTAGE_UNDER_WARN);
|
||||
static SENSOR_DEVICE_ATTR(in1_crit_max, S_IRUGO | S_IWUSR, ina209_show_value,
|
||||
ina209_set_value, INA209_BUS_VOLTAGE_OVER_LIMIT);
|
||||
static SENSOR_DEVICE_ATTR(in1_crit_min, S_IRUGO | S_IWUSR, ina209_show_value,
|
||||
ina209_set_value, INA209_BUS_VOLTAGE_UNDER_LIMIT);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(in1_min_alarm, S_IRUGO, ina209_show_alarm, NULL,
|
||||
1 << 14);
|
||||
static SENSOR_DEVICE_ATTR(in1_max_alarm, S_IRUGO, ina209_show_alarm, NULL,
|
||||
1 << 15);
|
||||
static SENSOR_DEVICE_ATTR(in1_crit_min_alarm, S_IRUGO, ina209_show_alarm, NULL,
|
||||
1 << 9);
|
||||
static SENSOR_DEVICE_ATTR(in1_crit_max_alarm, S_IRUGO, ina209_show_alarm, NULL,
|
||||
1 << 10);
|
||||
|
||||
/* Power */
|
||||
static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, ina209_show_value, NULL,
|
||||
INA209_POWER);
|
||||
static SENSOR_DEVICE_ATTR(power1_input_highest, S_IRUGO, ina209_show_value,
|
||||
NULL, INA209_POWER_PEAK);
|
||||
static SENSOR_DEVICE_ATTR(power1_reset_history, S_IWUSR, NULL,
|
||||
ina209_reset_history, 1 << 4);
|
||||
static SENSOR_DEVICE_ATTR(power1_max, S_IRUGO | S_IWUSR, ina209_show_value,
|
||||
ina209_set_value, INA209_POWER_WARN);
|
||||
static SENSOR_DEVICE_ATTR(power1_crit, S_IRUGO | S_IWUSR, ina209_show_value,
|
||||
ina209_set_value, INA209_POWER_OVER_LIMIT);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(power1_max_alarm, S_IRUGO, ina209_show_alarm, NULL,
|
||||
1 << 13);
|
||||
static SENSOR_DEVICE_ATTR(power1_crit_alarm, S_IRUGO, ina209_show_alarm, NULL,
|
||||
1 << 8);
|
||||
|
||||
/* Current */
|
||||
static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ina209_show_value, NULL,
|
||||
INA209_CURRENT);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR,
|
||||
ina209_show_interval, ina209_set_interval, 0);
|
||||
|
||||
/*
|
||||
* Finally, construct an array of pointers to members of the above objects,
|
||||
* as required for sysfs_create_group()
|
||||
*/
|
||||
static struct attribute *ina209_attributes[] = {
|
||||
&sensor_dev_attr_in0_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in0_input_highest.dev_attr.attr,
|
||||
&sensor_dev_attr_in0_input_lowest.dev_attr.attr,
|
||||
&sensor_dev_attr_in0_reset_history.dev_attr.attr,
|
||||
&sensor_dev_attr_in0_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in0_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in0_crit_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in0_crit_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in0_max_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_in0_min_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_in0_crit_max_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_in0_crit_min_alarm.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_in1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in1_input_highest.dev_attr.attr,
|
||||
&sensor_dev_attr_in1_input_lowest.dev_attr.attr,
|
||||
&sensor_dev_attr_in1_reset_history.dev_attr.attr,
|
||||
&sensor_dev_attr_in1_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in1_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in1_crit_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in1_crit_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in1_max_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_in1_min_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_in1_crit_max_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_in1_crit_min_alarm.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_power1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_power1_input_highest.dev_attr.attr,
|
||||
&sensor_dev_attr_power1_reset_history.dev_attr.attr,
|
||||
&sensor_dev_attr_power1_max.dev_attr.attr,
|
||||
&sensor_dev_attr_power1_crit.dev_attr.attr,
|
||||
&sensor_dev_attr_power1_max_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_power1_crit_alarm.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_curr1_input.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_update_interval.dev_attr.attr,
|
||||
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group ina209_group = {
|
||||
.attrs = ina209_attributes,
|
||||
};
|
||||
|
||||
static void ina209_restore_conf(struct i2c_client *client,
|
||||
struct ina209_data *data)
|
||||
{
|
||||
/* Restore initial configuration */
|
||||
i2c_smbus_write_word_swapped(client, INA209_CONFIGURATION,
|
||||
data->config_orig);
|
||||
i2c_smbus_write_word_swapped(client, INA209_CALIBRATION,
|
||||
data->calibration_orig);
|
||||
}
|
||||
|
||||
static int ina209_init_client(struct i2c_client *client,
|
||||
struct ina209_data *data)
|
||||
{
|
||||
struct ina2xx_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||
u32 shunt;
|
||||
int reg;
|
||||
|
||||
reg = i2c_smbus_read_word_swapped(client, INA209_CALIBRATION);
|
||||
if (reg < 0)
|
||||
return reg;
|
||||
data->calibration_orig = reg;
|
||||
|
||||
reg = i2c_smbus_read_word_swapped(client, INA209_CONFIGURATION);
|
||||
if (reg < 0)
|
||||
return reg;
|
||||
data->config_orig = reg;
|
||||
|
||||
if (pdata) {
|
||||
if (pdata->shunt_uohms <= 0)
|
||||
return -EINVAL;
|
||||
shunt = pdata->shunt_uohms;
|
||||
} else if (!of_property_read_u32(client->dev.of_node, "shunt-resistor",
|
||||
&shunt)) {
|
||||
if (shunt == 0)
|
||||
return -EINVAL;
|
||||
} else {
|
||||
shunt = data->calibration_orig ?
|
||||
40960000 / data->calibration_orig : INA209_SHUNT_DEFAULT;
|
||||
}
|
||||
|
||||
i2c_smbus_write_word_swapped(client, INA209_CONFIGURATION,
|
||||
INA209_CONFIG_DEFAULT);
|
||||
data->update_interval = ina209_interval_from_reg(INA209_CONFIG_DEFAULT);
|
||||
|
||||
/*
|
||||
* Calibrate current LSB to 1mA. Shunt is in uOhms.
|
||||
* See equation 13 in datasheet.
|
||||
*/
|
||||
i2c_smbus_write_word_swapped(client, INA209_CALIBRATION,
|
||||
clamp_val(40960000 / shunt, 1, 65535));
|
||||
|
||||
/* Clear status register */
|
||||
i2c_smbus_read_word_swapped(client, INA209_STATUS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ina209_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct ina209_data *data;
|
||||
int ret;
|
||||
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
|
||||
return -ENODEV;
|
||||
|
||||
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(client, data);
|
||||
mutex_init(&data->update_lock);
|
||||
|
||||
ret = ina209_init_client(client, data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Register sysfs hooks */
|
||||
ret = sysfs_create_group(&client->dev.kobj, &ina209_group);
|
||||
if (ret)
|
||||
goto out_restore_conf;
|
||||
|
||||
data->hwmon_dev = hwmon_device_register(&client->dev);
|
||||
if (IS_ERR(data->hwmon_dev)) {
|
||||
ret = PTR_ERR(data->hwmon_dev);
|
||||
goto out_hwmon_device_register;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_hwmon_device_register:
|
||||
sysfs_remove_group(&client->dev.kobj, &ina209_group);
|
||||
out_restore_conf:
|
||||
ina209_restore_conf(client, data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ina209_remove(struct i2c_client *client)
|
||||
{
|
||||
struct ina209_data *data = i2c_get_clientdata(client);
|
||||
|
||||
hwmon_device_unregister(data->hwmon_dev);
|
||||
sysfs_remove_group(&client->dev.kobj, &ina209_group);
|
||||
ina209_restore_conf(client, data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id ina209_id[] = {
|
||||
{ "ina209", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ina209_id);
|
||||
|
||||
/* This is the driver that will be inserted */
|
||||
static struct i2c_driver ina209_driver = {
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.driver = {
|
||||
.name = "ina209",
|
||||
},
|
||||
.probe = ina209_probe,
|
||||
.remove = ina209_remove,
|
||||
.id_table = ina209_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(ina209_driver);
|
||||
|
||||
MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>, Paul Hays <Paul.Hays@cattail.ca>, Guenter Roeck <linux@roeck-us.net>");
|
||||
MODULE_DESCRIPTION("INA209 driver");
|
||||
MODULE_LICENSE("GPL");
|
@@ -19,6 +19,8 @@
|
||||
* IT8726F Super I/O chip w/LPC interface
|
||||
* IT8728F Super I/O chip w/LPC interface
|
||||
* IT8758E Super I/O chip w/LPC interface
|
||||
* IT8771E Super I/O chip w/LPC interface
|
||||
* IT8772E Super I/O chip w/LPC interface
|
||||
* IT8782F Super I/O chip w/LPC interface
|
||||
* IT8783E/F Super I/O chip w/LPC interface
|
||||
* Sis950 A clone of the IT8705F
|
||||
@@ -61,8 +63,8 @@
|
||||
|
||||
#define DRVNAME "it87"
|
||||
|
||||
enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728, it8782,
|
||||
it8783 };
|
||||
enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728, it8771,
|
||||
it8772, it8782, it8783 };
|
||||
|
||||
static unsigned short force_id;
|
||||
module_param(force_id, ushort, 0);
|
||||
@@ -140,6 +142,8 @@ static inline void superio_exit(void)
|
||||
#define IT8721F_DEVID 0x8721
|
||||
#define IT8726F_DEVID 0x8726
|
||||
#define IT8728F_DEVID 0x8728
|
||||
#define IT8771E_DEVID 0x8771
|
||||
#define IT8772E_DEVID 0x8772
|
||||
#define IT8782F_DEVID 0x8782
|
||||
#define IT8783E_DEVID 0x8783
|
||||
#define IT87_ACT_REG 0x30
|
||||
@@ -281,6 +285,24 @@ static const struct it87_devices it87_devices[] = {
|
||||
| FEAT_TEMP_OFFSET | FEAT_TEMP_PECI,
|
||||
.peci_mask = 0x07,
|
||||
},
|
||||
[it8771] = {
|
||||
.name = "it8771",
|
||||
.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
|
||||
| FEAT_TEMP_OFFSET | FEAT_TEMP_PECI,
|
||||
/* PECI: guesswork */
|
||||
/* 12mV ADC (OHM) */
|
||||
/* 16 bit fans (OHM) */
|
||||
.peci_mask = 0x07,
|
||||
},
|
||||
[it8772] = {
|
||||
.name = "it8772",
|
||||
.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
|
||||
| FEAT_TEMP_OFFSET | FEAT_TEMP_PECI,
|
||||
/* PECI (coreboot) */
|
||||
/* 12mV ADC (HWSensors4, OHM) */
|
||||
/* 16 bit fans (HWSensors4, OHM) */
|
||||
.peci_mask = 0x07,
|
||||
},
|
||||
[it8782] = {
|
||||
.name = "it8782",
|
||||
.features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
|
||||
@@ -384,7 +406,7 @@ static int adc_lsb(const struct it87_data *data, int nr)
|
||||
static u8 in_to_reg(const struct it87_data *data, int nr, long val)
|
||||
{
|
||||
val = DIV_ROUND_CLOSEST(val, adc_lsb(data, nr));
|
||||
return SENSORS_LIMIT(val, 0, 255);
|
||||
return clamp_val(val, 0, 255);
|
||||
}
|
||||
|
||||
static int in_from_reg(const struct it87_data *data, int nr, int val)
|
||||
@@ -396,16 +418,15 @@ static inline u8 FAN_TO_REG(long rpm, int div)
|
||||
{
|
||||
if (rpm == 0)
|
||||
return 255;
|
||||
rpm = SENSORS_LIMIT(rpm, 1, 1000000);
|
||||
return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
|
||||
254);
|
||||
rpm = clamp_val(rpm, 1, 1000000);
|
||||
return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
|
||||
}
|
||||
|
||||
static inline u16 FAN16_TO_REG(long rpm)
|
||||
{
|
||||
if (rpm == 0)
|
||||
return 0xffff;
|
||||
return SENSORS_LIMIT((1350000 + rpm) / (rpm * 2), 1, 0xfffe);
|
||||
return clamp_val((1350000 + rpm) / (rpm * 2), 1, 0xfffe);
|
||||
}
|
||||
|
||||
#define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : (val) == 255 ? 0 : \
|
||||
@@ -414,8 +435,8 @@ static inline u16 FAN16_TO_REG(long rpm)
|
||||
#define FAN16_FROM_REG(val) ((val) == 0 ? -1 : (val) == 0xffff ? 0 : \
|
||||
1350000 / ((val) * 2))
|
||||
|
||||
#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val) < 0 ? (((val) - 500) / 1000) : \
|
||||
((val) + 500) / 1000), -128, 127))
|
||||
#define TEMP_TO_REG(val) (clamp_val(((val) < 0 ? (((val) - 500) / 1000) : \
|
||||
((val) + 500) / 1000), -128, 127))
|
||||
#define TEMP_FROM_REG(val) ((val) * 1000)
|
||||
|
||||
static u8 pwm_to_reg(const struct it87_data *data, long val)
|
||||
@@ -1709,6 +1730,12 @@ static int __init it87_find(unsigned short *address,
|
||||
case IT8728F_DEVID:
|
||||
sio_data->type = it8728;
|
||||
break;
|
||||
case IT8771E_DEVID:
|
||||
sio_data->type = it8771;
|
||||
break;
|
||||
case IT8772E_DEVID:
|
||||
sio_data->type = it8772;
|
||||
break;
|
||||
case IT8782F_DEVID:
|
||||
sio_data->type = it8782;
|
||||
break;
|
||||
@@ -1826,10 +1853,11 @@ static int __init it87_find(unsigned short *address,
|
||||
|
||||
reg = superio_inb(IT87_SIO_GPIO3_REG);
|
||||
if (sio_data->type == it8721 || sio_data->type == it8728 ||
|
||||
sio_data->type == it8771 || sio_data->type == it8772 ||
|
||||
sio_data->type == it8782) {
|
||||
/*
|
||||
* IT8721F/IT8758E, and IT8782F don't have VID pins
|
||||
* at all, not sure about the IT8728F.
|
||||
* at all, not sure about the IT8728F and compatibles.
|
||||
*/
|
||||
sio_data->skip_vid = 1;
|
||||
} else {
|
||||
@@ -1883,7 +1911,9 @@ static int __init it87_find(unsigned short *address,
|
||||
if (reg & (1 << 0))
|
||||
sio_data->internal |= (1 << 0);
|
||||
if ((reg & (1 << 1)) || sio_data->type == it8721 ||
|
||||
sio_data->type == it8728)
|
||||
sio_data->type == it8728 ||
|
||||
sio_data->type == it8771 ||
|
||||
sio_data->type == it8772)
|
||||
sio_data->internal |= (1 << 1);
|
||||
|
||||
/*
|
||||
|
@@ -103,6 +103,9 @@ static const unsigned short normal_i2c[] = {
|
||||
#define MCP98243_DEVID 0x2100
|
||||
#define MCP98243_DEVID_MASK 0xfffc
|
||||
|
||||
#define MCP98244_DEVID 0x2200
|
||||
#define MCP98244_DEVID_MASK 0xfffc
|
||||
|
||||
#define MCP9843_DEVID 0x0000 /* Also matches mcp9805 */
|
||||
#define MCP9843_DEVID_MASK 0xfffe
|
||||
|
||||
@@ -147,6 +150,7 @@ static struct jc42_chips jc42_chips[] = {
|
||||
{ MCP_MANID, MCP9804_DEVID, MCP9804_DEVID_MASK },
|
||||
{ MCP_MANID, MCP98242_DEVID, MCP98242_DEVID_MASK },
|
||||
{ MCP_MANID, MCP98243_DEVID, MCP98243_DEVID_MASK },
|
||||
{ MCP_MANID, MCP98244_DEVID, MCP98244_DEVID_MASK },
|
||||
{ MCP_MANID, MCP9843_DEVID, MCP9843_DEVID_MASK },
|
||||
{ NXP_MANID, SE97_DEVID, SE97_DEVID_MASK },
|
||||
{ ONS_MANID, CAT6095_DEVID, CAT6095_DEVID_MASK },
|
||||
@@ -237,9 +241,9 @@ static struct i2c_driver jc42_driver = {
|
||||
|
||||
static u16 jc42_temp_to_reg(int temp, bool extended)
|
||||
{
|
||||
int ntemp = SENSORS_LIMIT(temp,
|
||||
extended ? JC42_TEMP_MIN_EXTENDED :
|
||||
JC42_TEMP_MIN, JC42_TEMP_MAX);
|
||||
int ntemp = clamp_val(temp,
|
||||
extended ? JC42_TEMP_MIN_EXTENDED :
|
||||
JC42_TEMP_MIN, JC42_TEMP_MAX);
|
||||
|
||||
/* convert from 0.001 to 0.0625 resolution */
|
||||
return (ntemp * 2 / 125) & 0x1fff;
|
||||
|
@@ -209,9 +209,9 @@ static inline int lut_temp_to_reg(struct lm63_data *data, long val)
|
||||
{
|
||||
val -= data->temp2_offset;
|
||||
if (data->lut_temp_highres)
|
||||
return DIV_ROUND_CLOSEST(SENSORS_LIMIT(val, 0, 127500), 500);
|
||||
return DIV_ROUND_CLOSEST(clamp_val(val, 0, 127500), 500);
|
||||
else
|
||||
return DIV_ROUND_CLOSEST(SENSORS_LIMIT(val, 0, 127000), 1000);
|
||||
return DIV_ROUND_CLOSEST(clamp_val(val, 0, 127000), 1000);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -415,7 +415,7 @@ static ssize_t set_pwm1(struct device *dev, struct device_attribute *devattr,
|
||||
return err;
|
||||
|
||||
reg = nr ? LM63_REG_LUT_PWM(nr - 1) : LM63_REG_PWM_VALUE;
|
||||
val = SENSORS_LIMIT(val, 0, 255);
|
||||
val = clamp_val(val, 0, 255);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->pwm1[nr] = data->pwm_highres ? val :
|
||||
@@ -700,7 +700,7 @@ static ssize_t set_update_interval(struct device *dev,
|
||||
return err;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
lm63_set_convrate(client, data, SENSORS_LIMIT(val, 0, 100000));
|
||||
lm63_set_convrate(client, data, clamp_val(val, 0, 100000));
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
return count;
|
||||
|
@@ -8,6 +8,7 @@
|
||||
* Guillaume Ligneul <guillaume.ligneul@gmail.com>
|
||||
* Adrien Demarez <adrien.demarez@bolloretelecom.eu>
|
||||
* Jeremy Laine <jeremy.laine@bolloretelecom.eu>
|
||||
* Chris Verges <kg4ysn@gmail.com>
|
||||
*
|
||||
* This software program is licensed subject to the GNU General Public License
|
||||
* (GPL).Version 2,June 1991, available at
|
||||
@@ -36,12 +37,31 @@ static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4c,
|
||||
|
||||
#define LM73_ID 0x9001 /* 0x0190, byte-swapped */
|
||||
#define DRVNAME "lm73"
|
||||
#define LM73_TEMP_MIN (-40)
|
||||
#define LM73_TEMP_MAX 150
|
||||
#define LM73_TEMP_MIN (-256000 / 250)
|
||||
#define LM73_TEMP_MAX (255750 / 250)
|
||||
|
||||
#define LM73_CTRL_RES_SHIFT 5
|
||||
#define LM73_CTRL_RES_MASK (BIT(5) | BIT(6))
|
||||
#define LM73_CTRL_TO_MASK BIT(7)
|
||||
|
||||
#define LM73_CTRL_HI_SHIFT 2
|
||||
#define LM73_CTRL_LO_SHIFT 1
|
||||
|
||||
static const unsigned short lm73_convrates[] = {
|
||||
14, /* 11-bits (0.25000 C/LSB): RES1 Bit = 0, RES0 Bit = 0 */
|
||||
28, /* 12-bits (0.12500 C/LSB): RES1 Bit = 0, RES0 Bit = 1 */
|
||||
56, /* 13-bits (0.06250 C/LSB): RES1 Bit = 1, RES0 Bit = 0 */
|
||||
112, /* 14-bits (0.03125 C/LSB): RES1 Bit = 1, RES0 Bit = 1 */
|
||||
};
|
||||
|
||||
struct lm73_data {
|
||||
struct device *hwmon_dev;
|
||||
struct mutex lock;
|
||||
u8 ctrl; /* control register value */
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
|
||||
static ssize_t set_temp(struct device *dev, struct device_attribute *da,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
@@ -56,8 +76,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da,
|
||||
return status;
|
||||
|
||||
/* Write value */
|
||||
value = (short) SENSORS_LIMIT(temp/250, (LM73_TEMP_MIN*4),
|
||||
(LM73_TEMP_MAX*4)) << 5;
|
||||
value = clamp_val(temp / 250, LM73_TEMP_MIN, LM73_TEMP_MAX) << 5;
|
||||
err = i2c_smbus_write_word_swapped(client, attr->index, value);
|
||||
return (err < 0) ? err : count;
|
||||
}
|
||||
@@ -79,6 +98,73 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *da,
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", temp);
|
||||
}
|
||||
|
||||
static ssize_t set_convrate(struct device *dev, struct device_attribute *da,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct lm73_data *data = i2c_get_clientdata(client);
|
||||
unsigned long convrate;
|
||||
s32 err;
|
||||
int res = 0;
|
||||
|
||||
err = kstrtoul(buf, 10, &convrate);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/*
|
||||
* Convert the desired conversion rate into register bits.
|
||||
* res is already initialized, and everything past the second-to-last
|
||||
* value in the array is treated as belonging to the last value
|
||||
* in the array.
|
||||
*/
|
||||
while (res < (ARRAY_SIZE(lm73_convrates) - 1) &&
|
||||
convrate > lm73_convrates[res])
|
||||
res++;
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
data->ctrl &= LM73_CTRL_TO_MASK;
|
||||
data->ctrl |= res << LM73_CTRL_RES_SHIFT;
|
||||
err = i2c_smbus_write_byte_data(client, LM73_REG_CTRL, data->ctrl);
|
||||
mutex_unlock(&data->lock);
|
||||
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t show_convrate(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct lm73_data *data = i2c_get_clientdata(client);
|
||||
int res;
|
||||
|
||||
res = (data->ctrl & LM73_CTRL_RES_MASK) >> LM73_CTRL_RES_SHIFT;
|
||||
return scnprintf(buf, PAGE_SIZE, "%hu\n", lm73_convrates[res]);
|
||||
}
|
||||
|
||||
static ssize_t show_maxmin_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);
|
||||
struct lm73_data *data = i2c_get_clientdata(client);
|
||||
s32 ctrl;
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
ctrl = i2c_smbus_read_byte_data(client, LM73_REG_CTRL);
|
||||
if (ctrl < 0)
|
||||
goto abort;
|
||||
data->ctrl = ctrl;
|
||||
mutex_unlock(&data->lock);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", (ctrl >> attr->index) & 1);
|
||||
|
||||
abort:
|
||||
mutex_unlock(&data->lock);
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
@@ -90,13 +176,20 @@ static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO,
|
||||
show_temp, set_temp, LM73_REG_MIN);
|
||||
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
|
||||
show_temp, NULL, LM73_REG_INPUT);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO,
|
||||
show_convrate, set_convrate, 0);
|
||||
static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO,
|
||||
show_maxmin_alarm, NULL, LM73_CTRL_HI_SHIFT);
|
||||
static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO,
|
||||
show_maxmin_alarm, NULL, LM73_CTRL_LO_SHIFT);
|
||||
|
||||
static struct attribute *lm73_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_update_interval.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -111,23 +204,36 @@ static const struct attribute_group lm73_group = {
|
||||
static int
|
||||
lm73_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
{
|
||||
struct device *hwmon_dev;
|
||||
int status;
|
||||
struct lm73_data *data;
|
||||
int ctrl;
|
||||
|
||||
data = devm_kzalloc(&client->dev, sizeof(struct lm73_data),
|
||||
GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(client, data);
|
||||
mutex_init(&data->lock);
|
||||
|
||||
ctrl = i2c_smbus_read_byte_data(client, LM73_REG_CTRL);
|
||||
if (ctrl < 0)
|
||||
return ctrl;
|
||||
data->ctrl = ctrl;
|
||||
|
||||
/* Register sysfs hooks */
|
||||
status = sysfs_create_group(&client->dev.kobj, &lm73_group);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
hwmon_dev = hwmon_device_register(&client->dev);
|
||||
if (IS_ERR(hwmon_dev)) {
|
||||
status = PTR_ERR(hwmon_dev);
|
||||
data->hwmon_dev = hwmon_device_register(&client->dev);
|
||||
if (IS_ERR(data->hwmon_dev)) {
|
||||
status = PTR_ERR(data->hwmon_dev);
|
||||
goto exit_remove;
|
||||
}
|
||||
i2c_set_clientdata(client, hwmon_dev);
|
||||
|
||||
dev_info(&client->dev, "%s: sensor '%s'\n",
|
||||
dev_name(hwmon_dev), client->name);
|
||||
dev_name(data->hwmon_dev), client->name);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -138,9 +244,9 @@ exit_remove:
|
||||
|
||||
static int lm73_remove(struct i2c_client *client)
|
||||
{
|
||||
struct device *hwmon_dev = i2c_get_clientdata(client);
|
||||
struct lm73_data *data = i2c_get_clientdata(client);
|
||||
|
||||
hwmon_device_unregister(hwmon_dev);
|
||||
hwmon_device_unregister(data->hwmon_dev);
|
||||
sysfs_remove_group(&client->dev.kobj, &lm73_group);
|
||||
return 0;
|
||||
}
|
||||
|
@@ -36,7 +36,7 @@
|
||||
REG: (0.5C/bit, two's complement) << 7 */
|
||||
static inline u16 LM75_TEMP_TO_REG(long temp)
|
||||
{
|
||||
int ntemp = SENSORS_LIMIT(temp, LM75_TEMP_MIN, LM75_TEMP_MAX);
|
||||
int ntemp = clamp_val(temp, LM75_TEMP_MIN, LM75_TEMP_MAX);
|
||||
ntemp += (ntemp < 0 ? -250 : 250);
|
||||
return (u16)((ntemp / 500) << 7);
|
||||
}
|
||||
|
@@ -101,7 +101,7 @@ static struct i2c_driver lm77_driver = {
|
||||
*/
|
||||
static inline s16 LM77_TEMP_TO_REG(int temp)
|
||||
{
|
||||
int ntemp = SENSORS_LIMIT(temp, LM77_TEMP_MIN, LM77_TEMP_MAX);
|
||||
int ntemp = clamp_val(temp, LM77_TEMP_MIN, LM77_TEMP_MAX);
|
||||
return (ntemp / 500) * 8;
|
||||
}
|
||||
|
||||
|
@@ -85,7 +85,7 @@ enum chips { lm78, lm79 };
|
||||
*/
|
||||
static inline u8 IN_TO_REG(unsigned long val)
|
||||
{
|
||||
unsigned long nval = SENSORS_LIMIT(val, 0, 4080);
|
||||
unsigned long nval = clamp_val(val, 0, 4080);
|
||||
return (nval + 8) / 16;
|
||||
}
|
||||
#define IN_FROM_REG(val) ((val) * 16)
|
||||
@@ -94,7 +94,7 @@ static inline u8 FAN_TO_REG(long rpm, int div)
|
||||
{
|
||||
if (rpm <= 0)
|
||||
return 255;
|
||||
return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
|
||||
return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
|
||||
}
|
||||
|
||||
static inline int FAN_FROM_REG(u8 val, int div)
|
||||
@@ -108,7 +108,7 @@ static inline int FAN_FROM_REG(u8 val, int div)
|
||||
*/
|
||||
static inline s8 TEMP_TO_REG(int val)
|
||||
{
|
||||
int nval = SENSORS_LIMIT(val, -128000, 127000) ;
|
||||
int nval = clamp_val(val, -128000, 127000) ;
|
||||
return nval < 0 ? (nval - 500) / 1000 : (nval + 500) / 1000;
|
||||
}
|
||||
|
||||
|
@@ -72,15 +72,15 @@ static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
|
||||
* Fixing this is just not worth it.
|
||||
*/
|
||||
|
||||
#define IN_TO_REG(val) (SENSORS_LIMIT(((val) + 5) / 10, 0, 255))
|
||||
#define IN_TO_REG(val) (clamp_val(((val) + 5) / 10, 0, 255))
|
||||
#define IN_FROM_REG(val) ((val) * 10)
|
||||
|
||||
static inline unsigned char FAN_TO_REG(unsigned rpm, unsigned div)
|
||||
{
|
||||
if (rpm == 0)
|
||||
return 255;
|
||||
rpm = SENSORS_LIMIT(rpm, 1, 1000000);
|
||||
return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
|
||||
rpm = clamp_val(rpm, 1, 1000000);
|
||||
return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
|
||||
}
|
||||
|
||||
#define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : \
|
||||
@@ -102,7 +102,7 @@ static inline long TEMP_FROM_REG(u16 temp)
|
||||
#define TEMP_LIMIT_FROM_REG(val) (((val) > 0x80 ? \
|
||||
(val) - 0x100 : (val)) * 1000)
|
||||
|
||||
#define TEMP_LIMIT_TO_REG(val) SENSORS_LIMIT((val) < 0 ? \
|
||||
#define TEMP_LIMIT_TO_REG(val) clamp_val((val) < 0 ? \
|
||||
((val) - 500) / 1000 : ((val) + 500) / 1000, 0, 255)
|
||||
|
||||
#define DIV_FROM_REG(val) (1 << (val))
|
||||
|
@@ -139,7 +139,7 @@ static const int lm85_scaling[] = { /* .001 Volts */
|
||||
#define SCALE(val, from, to) (((val) * (to) + ((from) / 2)) / (from))
|
||||
|
||||
#define INS_TO_REG(n, val) \
|
||||
SENSORS_LIMIT(SCALE(val, lm85_scaling[n], 192), 0, 255)
|
||||
clamp_val(SCALE(val, lm85_scaling[n], 192), 0, 255)
|
||||
|
||||
#define INSEXT_FROM_REG(n, val, ext) \
|
||||
SCALE(((val) << 4) + (ext), 192 << 4, lm85_scaling[n])
|
||||
@@ -151,19 +151,19 @@ static inline u16 FAN_TO_REG(unsigned long val)
|
||||
{
|
||||
if (!val)
|
||||
return 0xffff;
|
||||
return SENSORS_LIMIT(5400000 / val, 1, 0xfffe);
|
||||
return clamp_val(5400000 / val, 1, 0xfffe);
|
||||
}
|
||||
#define FAN_FROM_REG(val) ((val) == 0 ? -1 : (val) == 0xffff ? 0 : \
|
||||
5400000 / (val))
|
||||
|
||||
/* Temperature is reported in .001 degC increments */
|
||||
#define TEMP_TO_REG(val) \
|
||||
SENSORS_LIMIT(SCALE(val, 1000, 1), -127, 127)
|
||||
clamp_val(SCALE(val, 1000, 1), -127, 127)
|
||||
#define TEMPEXT_FROM_REG(val, ext) \
|
||||
SCALE(((val) << 4) + (ext), 16, 1000)
|
||||
#define TEMP_FROM_REG(val) ((val) * 1000)
|
||||
|
||||
#define PWM_TO_REG(val) SENSORS_LIMIT(val, 0, 255)
|
||||
#define PWM_TO_REG(val) clamp_val(val, 0, 255)
|
||||
#define PWM_FROM_REG(val) (val)
|
||||
|
||||
|
||||
@@ -258,7 +258,7 @@ static int ZONE_TO_REG(int zone)
|
||||
return i << 5;
|
||||
}
|
||||
|
||||
#define HYST_TO_REG(val) SENSORS_LIMIT(((val) + 500) / 1000, 0, 15)
|
||||
#define HYST_TO_REG(val) clamp_val(((val) + 500) / 1000, 0, 15)
|
||||
#define HYST_FROM_REG(val) ((val) * 1000)
|
||||
|
||||
/*
|
||||
|
@@ -931,7 +931,7 @@ static ssize_t set_update_interval(struct device *dev,
|
||||
return err;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
lm90_set_convrate(client, data, SENSORS_LIMIT(val, 0, 100000));
|
||||
lm90_set_convrate(client, data, clamp_val(val, 0, 100000));
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
return count;
|
||||
|
@@ -371,8 +371,8 @@ 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 = SENSORS_LIMIT(val,
|
||||
lm93_vin_val_min[nr], lm93_vin_val_max[nr]);
|
||||
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;
|
||||
@@ -385,8 +385,8 @@ static u8 LM93_IN_TO_REG(int nr, unsigned val)
|
||||
const long intercept = uV_min - slope * lm93_vin_reg_min[nr];
|
||||
|
||||
u8 result = ((uV - intercept + (slope/2)) / slope);
|
||||
result = SENSORS_LIMIT(result,
|
||||
lm93_vin_reg_min[nr], lm93_vin_reg_max[nr]);
|
||||
result = clamp_val(result,
|
||||
lm93_vin_reg_min[nr], lm93_vin_reg_max[nr]);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -411,10 +411,10 @@ static u8 LM93_IN_REL_TO_REG(unsigned val, int upper, int vid)
|
||||
{
|
||||
long uV_offset = vid * 1000 - val * 10000;
|
||||
if (upper) {
|
||||
uV_offset = SENSORS_LIMIT(uV_offset, 12500, 200000);
|
||||
uV_offset = clamp_val(uV_offset, 12500, 200000);
|
||||
return (u8)((uV_offset / 12500 - 1) << 4);
|
||||
} else {
|
||||
uV_offset = SENSORS_LIMIT(uV_offset, -400000, -25000);
|
||||
uV_offset = clamp_val(uV_offset, -400000, -25000);
|
||||
return (u8)((uV_offset / -25000 - 1) << 0);
|
||||
}
|
||||
}
|
||||
@@ -437,7 +437,7 @@ static int LM93_TEMP_FROM_REG(u8 reg)
|
||||
*/
|
||||
static u8 LM93_TEMP_TO_REG(long temp)
|
||||
{
|
||||
int ntemp = SENSORS_LIMIT(temp, LM93_TEMP_MIN, LM93_TEMP_MAX);
|
||||
int ntemp = clamp_val(temp, LM93_TEMP_MIN, LM93_TEMP_MAX);
|
||||
ntemp += (ntemp < 0 ? -500 : 500);
|
||||
return (u8)(ntemp / 1000);
|
||||
}
|
||||
@@ -472,7 +472,7 @@ static u8 LM93_TEMP_OFFSET_TO_REG(int off, int mode)
|
||||
{
|
||||
int factor = mode ? 5 : 10;
|
||||
|
||||
off = SENSORS_LIMIT(off, LM93_TEMP_OFFSET_MIN,
|
||||
off = clamp_val(off, LM93_TEMP_OFFSET_MIN,
|
||||
mode ? LM93_TEMP_OFFSET_MAX1 : LM93_TEMP_OFFSET_MAX0);
|
||||
return (u8)((off + factor/2) / factor);
|
||||
}
|
||||
@@ -620,8 +620,8 @@ static u16 LM93_FAN_TO_REG(long rpm)
|
||||
if (rpm == 0) {
|
||||
count = 0x3fff;
|
||||
} else {
|
||||
rpm = SENSORS_LIMIT(rpm, 1, 1000000);
|
||||
count = SENSORS_LIMIT((1350000 + rpm) / rpm, 1, 0x3ffe);
|
||||
rpm = clamp_val(rpm, 1, 1000000);
|
||||
count = clamp_val((1350000 + rpm) / rpm, 1, 0x3ffe);
|
||||
}
|
||||
|
||||
regs = count << 2;
|
||||
@@ -692,7 +692,7 @@ static int LM93_RAMP_FROM_REG(u8 reg)
|
||||
*/
|
||||
static u8 LM93_RAMP_TO_REG(int ramp)
|
||||
{
|
||||
ramp = SENSORS_LIMIT(ramp, LM93_RAMP_MIN, LM93_RAMP_MAX);
|
||||
ramp = clamp_val(ramp, LM93_RAMP_MIN, LM93_RAMP_MAX);
|
||||
return (u8)((ramp + 2) / 5);
|
||||
}
|
||||
|
||||
@@ -702,7 +702,7 @@ static u8 LM93_RAMP_TO_REG(int ramp)
|
||||
*/
|
||||
static u8 LM93_PROCHOT_TO_REG(long prochot)
|
||||
{
|
||||
prochot = SENSORS_LIMIT(prochot, 0, 255);
|
||||
prochot = clamp_val(prochot, 0, 255);
|
||||
return (u8)prochot;
|
||||
}
|
||||
|
||||
@@ -2052,7 +2052,7 @@ static ssize_t store_pwm_auto_channels(struct device *dev,
|
||||
return err;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->block9[nr][LM93_PWM_CTL1] = SENSORS_LIMIT(val, 0, 255);
|
||||
data->block9[nr][LM93_PWM_CTL1] = clamp_val(val, 0, 255);
|
||||
lm93_write_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL1),
|
||||
data->block9[nr][LM93_PWM_CTL1]);
|
||||
mutex_unlock(&data->update_lock);
|
||||
@@ -2397,7 +2397,7 @@ static ssize_t store_prochot_override_duty_cycle(struct device *dev,
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->prochot_override = (data->prochot_override & 0xf0) |
|
||||
SENSORS_LIMIT(val, 0, 15);
|
||||
clamp_val(val, 0, 15);
|
||||
lm93_write_byte(client, LM93_REG_PROCHOT_OVERRIDE,
|
||||
data->prochot_override);
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
@@ -259,7 +259,7 @@ static ssize_t set_limit(struct device *dev, struct device_attribute *attr,
|
||||
|
||||
val /= 1000;
|
||||
|
||||
val = SENSORS_LIMIT(val, 0, (index == 6 ? 127 : 255));
|
||||
val = clamp_val(val, 0, (index == 6 ? 127 : 255));
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
|
||||
@@ -284,7 +284,7 @@ static ssize_t set_crit_hyst(struct device *dev, struct device_attribute *attr,
|
||||
|
||||
val /= 1000;
|
||||
|
||||
val = SENSORS_LIMIT(val, 0, 31);
|
||||
val = clamp_val(val, 0, 31);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
|
||||
|
@@ -118,7 +118,7 @@ static inline int LIMIT_TO_MV(int limit, int range)
|
||||
|
||||
static inline int MV_TO_LIMIT(int mv, int range)
|
||||
{
|
||||
return SENSORS_LIMIT(DIV_ROUND_CLOSEST(mv * 256, range), 0, 255);
|
||||
return clamp_val(DIV_ROUND_CLOSEST(mv * 256, range), 0, 255);
|
||||
}
|
||||
|
||||
static inline int ADC_TO_CURR(int adc, int gain)
|
||||
|
@@ -215,7 +215,7 @@ static ssize_t set_temp_max(struct device *dev,
|
||||
return ret;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->temp_max[index] = SENSORS_LIMIT(temp/1000, -128, 127);
|
||||
data->temp_max[index] = clamp_val(temp/1000, -128, 127);
|
||||
if (i2c_smbus_write_byte_data(client,
|
||||
MAX1668_REG_LIMH_WR(index),
|
||||
data->temp_max[index]))
|
||||
@@ -240,7 +240,7 @@ static ssize_t set_temp_min(struct device *dev,
|
||||
return ret;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->temp_min[index] = SENSORS_LIMIT(temp/1000, -128, 127);
|
||||
data->temp_min[index] = clamp_val(temp/1000, -128, 127);
|
||||
if (i2c_smbus_write_byte_data(client,
|
||||
MAX1668_REG_LIML_WR(index),
|
||||
data->temp_max[index]))
|
||||
|
@@ -74,7 +74,7 @@ static const int rpm_ranges[] = { 2000, 4000, 8000, 16000 };
|
||||
|
||||
#define FAN_FROM_REG(val, rpm_range) ((val) == 0 || (val) == 255 ? \
|
||||
0 : (rpm_ranges[rpm_range] * 30) / (val))
|
||||
#define TEMP_LIMIT_TO_REG(val) SENSORS_LIMIT((val) / 1000, 0, 255)
|
||||
#define TEMP_LIMIT_TO_REG(val) clamp_val((val) / 1000, 0, 255)
|
||||
|
||||
/*
|
||||
* Client data (each client gets its own)
|
||||
@@ -312,7 +312,7 @@ static ssize_t set_pwm(struct device *dev,
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
val = SENSORS_LIMIT(val, 0, 255);
|
||||
val = clamp_val(val, 0, 255);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->pwm[attr->index] = (u8)(val * 120 / 255);
|
||||
|
@@ -239,7 +239,7 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
|
||||
return err;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->temp_high[attr2->nr] = SENSORS_LIMIT(temp_to_reg(val), 0, 255);
|
||||
data->temp_high[attr2->nr] = clamp_val(temp_to_reg(val), 0, 255);
|
||||
i2c_smbus_write_byte_data(client, attr2->index,
|
||||
data->temp_high[attr2->nr]);
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
@@ -245,7 +245,7 @@ static ssize_t set_target(struct device *dev, struct device_attribute *devattr,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
rpm = SENSORS_LIMIT(rpm, FAN_RPM_MIN, FAN_RPM_MAX);
|
||||
rpm = clamp_val(rpm, FAN_RPM_MIN, FAN_RPM_MAX);
|
||||
|
||||
/*
|
||||
* Divide the required speed by 60 to get from rpm to rps, then
|
||||
@@ -313,7 +313,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
pwm = SENSORS_LIMIT(pwm, 0, 255);
|
||||
pwm = clamp_val(pwm, 0, 255);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
|
||||
|
726
drivers/hwmon/max6697.c
Normal file
726
drivers/hwmon/max6697.c
Normal file
@@ -0,0 +1,726 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Guenter Roeck <linux@roeck-us.net>
|
||||
*
|
||||
* based on max1668.c
|
||||
* Copyright (c) 2011 David George <david.george@ska.ac.za>
|
||||
*
|
||||
* 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/of.h>
|
||||
|
||||
#include <linux/platform_data/max6697.h>
|
||||
|
||||
enum chips { max6581, max6602, max6622, max6636, max6689, max6693, max6694,
|
||||
max6697, max6698, max6699 };
|
||||
|
||||
/* Report local sensor as temp1 */
|
||||
|
||||
static const u8 MAX6697_REG_TEMP[] = {
|
||||
0x07, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08 };
|
||||
static const u8 MAX6697_REG_TEMP_EXT[] = {
|
||||
0x57, 0x09, 0x52, 0x53, 0x54, 0x55, 0x56, 0 };
|
||||
static const u8 MAX6697_REG_MAX[] = {
|
||||
0x17, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x18 };
|
||||
static const u8 MAX6697_REG_CRIT[] = {
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27 };
|
||||
|
||||
/*
|
||||
* Map device tree / platform data register bit map to chip bit map.
|
||||
* Applies to alert register and over-temperature register.
|
||||
*/
|
||||
#define MAX6697_MAP_BITS(reg) ((((reg) & 0x7e) >> 1) | \
|
||||
(((reg) & 0x01) << 6) | ((reg) & 0x80))
|
||||
|
||||
#define MAX6697_REG_STAT(n) (0x44 + (n))
|
||||
|
||||
#define MAX6697_REG_CONFIG 0x41
|
||||
#define MAX6581_CONF_EXTENDED (1 << 1)
|
||||
#define MAX6693_CONF_BETA (1 << 2)
|
||||
#define MAX6697_CONF_RESISTANCE (1 << 3)
|
||||
#define MAX6697_CONF_TIMEOUT (1 << 5)
|
||||
#define MAX6697_REG_ALERT_MASK 0x42
|
||||
#define MAX6697_REG_OVERT_MASK 0x43
|
||||
|
||||
#define MAX6581_REG_RESISTANCE 0x4a
|
||||
#define MAX6581_REG_IDEALITY 0x4b
|
||||
#define MAX6581_REG_IDEALITY_SELECT 0x4c
|
||||
#define MAX6581_REG_OFFSET 0x4d
|
||||
#define MAX6581_REG_OFFSET_SELECT 0x4e
|
||||
|
||||
#define MAX6697_CONV_TIME 156 /* ms per channel, worst case */
|
||||
|
||||
struct max6697_chip_data {
|
||||
int channels;
|
||||
u32 have_ext;
|
||||
u32 have_crit;
|
||||
u32 have_fault;
|
||||
u8 valid_conf;
|
||||
const u8 *alarm_map;
|
||||
};
|
||||
|
||||
struct max6697_data {
|
||||
struct device *hwmon_dev;
|
||||
|
||||
enum chips type;
|
||||
const struct max6697_chip_data *chip;
|
||||
|
||||
int update_interval; /* in milli-seconds */
|
||||
int temp_offset; /* in degrees C */
|
||||
|
||||
struct mutex update_lock;
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
bool valid; /* true if following fields are valid */
|
||||
|
||||
/* 1x local and up to 7x remote */
|
||||
u8 temp[8][4]; /* [nr][0]=temp [1]=ext [2]=max [3]=crit */
|
||||
#define MAX6697_TEMP_INPUT 0
|
||||
#define MAX6697_TEMP_EXT 1
|
||||
#define MAX6697_TEMP_MAX 2
|
||||
#define MAX6697_TEMP_CRIT 3
|
||||
u32 alarms;
|
||||
};
|
||||
|
||||
/* Diode fault status bits on MAX6581 are right shifted by one bit */
|
||||
static const u8 max6581_alarm_map[] = {
|
||||
0, 0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23 };
|
||||
|
||||
static const struct max6697_chip_data max6697_chip_data[] = {
|
||||
[max6581] = {
|
||||
.channels = 8,
|
||||
.have_crit = 0xff,
|
||||
.have_ext = 0x7f,
|
||||
.have_fault = 0xfe,
|
||||
.valid_conf = MAX6581_CONF_EXTENDED | MAX6697_CONF_TIMEOUT,
|
||||
.alarm_map = max6581_alarm_map,
|
||||
},
|
||||
[max6602] = {
|
||||
.channels = 5,
|
||||
.have_crit = 0x12,
|
||||
.have_ext = 0x02,
|
||||
.have_fault = 0x1e,
|
||||
.valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT,
|
||||
},
|
||||
[max6622] = {
|
||||
.channels = 5,
|
||||
.have_crit = 0x12,
|
||||
.have_ext = 0x02,
|
||||
.have_fault = 0x1e,
|
||||
.valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT,
|
||||
},
|
||||
[max6636] = {
|
||||
.channels = 7,
|
||||
.have_crit = 0x72,
|
||||
.have_ext = 0x02,
|
||||
.have_fault = 0x7e,
|
||||
.valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT,
|
||||
},
|
||||
[max6689] = {
|
||||
.channels = 7,
|
||||
.have_crit = 0x72,
|
||||
.have_ext = 0x02,
|
||||
.have_fault = 0x7e,
|
||||
.valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT,
|
||||
},
|
||||
[max6693] = {
|
||||
.channels = 7,
|
||||
.have_crit = 0x72,
|
||||
.have_ext = 0x02,
|
||||
.have_fault = 0x7e,
|
||||
.valid_conf = MAX6697_CONF_RESISTANCE | MAX6693_CONF_BETA |
|
||||
MAX6697_CONF_TIMEOUT,
|
||||
},
|
||||
[max6694] = {
|
||||
.channels = 5,
|
||||
.have_crit = 0x12,
|
||||
.have_ext = 0x02,
|
||||
.have_fault = 0x1e,
|
||||
.valid_conf = MAX6697_CONF_RESISTANCE | MAX6693_CONF_BETA |
|
||||
MAX6697_CONF_TIMEOUT,
|
||||
},
|
||||
[max6697] = {
|
||||
.channels = 7,
|
||||
.have_crit = 0x72,
|
||||
.have_ext = 0x02,
|
||||
.have_fault = 0x7e,
|
||||
.valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT,
|
||||
},
|
||||
[max6698] = {
|
||||
.channels = 7,
|
||||
.have_crit = 0x72,
|
||||
.have_ext = 0x02,
|
||||
.have_fault = 0x0e,
|
||||
.valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT,
|
||||
},
|
||||
[max6699] = {
|
||||
.channels = 5,
|
||||
.have_crit = 0x12,
|
||||
.have_ext = 0x02,
|
||||
.have_fault = 0x1e,
|
||||
.valid_conf = MAX6697_CONF_RESISTANCE | MAX6697_CONF_TIMEOUT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct max6697_data *max6697_update_device(struct device *dev)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct max6697_data *data = i2c_get_clientdata(client);
|
||||
struct max6697_data *ret = data;
|
||||
int val;
|
||||
int i;
|
||||
u32 alarms;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
|
||||
if (data->valid &&
|
||||
!time_after(jiffies, data->last_updated
|
||||
+ msecs_to_jiffies(data->update_interval)))
|
||||
goto abort;
|
||||
|
||||
for (i = 0; i < data->chip->channels; i++) {
|
||||
if (data->chip->have_ext & (1 << i)) {
|
||||
val = i2c_smbus_read_byte_data(client,
|
||||
MAX6697_REG_TEMP_EXT[i]);
|
||||
if (unlikely(val < 0)) {
|
||||
ret = ERR_PTR(val);
|
||||
goto abort;
|
||||
}
|
||||
data->temp[i][MAX6697_TEMP_EXT] = val;
|
||||
}
|
||||
|
||||
val = i2c_smbus_read_byte_data(client, MAX6697_REG_TEMP[i]);
|
||||
if (unlikely(val < 0)) {
|
||||
ret = ERR_PTR(val);
|
||||
goto abort;
|
||||
}
|
||||
data->temp[i][MAX6697_TEMP_INPUT] = val;
|
||||
|
||||
val = i2c_smbus_read_byte_data(client, MAX6697_REG_MAX[i]);
|
||||
if (unlikely(val < 0)) {
|
||||
ret = ERR_PTR(val);
|
||||
goto abort;
|
||||
}
|
||||
data->temp[i][MAX6697_TEMP_MAX] = val;
|
||||
|
||||
if (data->chip->have_crit & (1 << i)) {
|
||||
val = i2c_smbus_read_byte_data(client,
|
||||
MAX6697_REG_CRIT[i]);
|
||||
if (unlikely(val < 0)) {
|
||||
ret = ERR_PTR(val);
|
||||
goto abort;
|
||||
}
|
||||
data->temp[i][MAX6697_TEMP_CRIT] = val;
|
||||
}
|
||||
}
|
||||
|
||||
alarms = 0;
|
||||
for (i = 0; i < 3; i++) {
|
||||
val = i2c_smbus_read_byte_data(client, MAX6697_REG_STAT(i));
|
||||
if (unlikely(val < 0)) {
|
||||
ret = ERR_PTR(val);
|
||||
goto abort;
|
||||
}
|
||||
alarms = (alarms << 8) | val;
|
||||
}
|
||||
data->alarms = alarms;
|
||||
data->last_updated = jiffies;
|
||||
data->valid = true;
|
||||
abort:
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t show_temp_input(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
int index = to_sensor_dev_attr(devattr)->index;
|
||||
struct max6697_data *data = max6697_update_device(dev);
|
||||
int temp;
|
||||
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
temp = (data->temp[index][MAX6697_TEMP_INPUT] - data->temp_offset) << 3;
|
||||
temp |= data->temp[index][MAX6697_TEMP_EXT] >> 5;
|
||||
|
||||
return sprintf(buf, "%d\n", temp * 125);
|
||||
}
|
||||
|
||||
static ssize_t show_temp(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
int nr = to_sensor_dev_attr_2(devattr)->nr;
|
||||
int index = to_sensor_dev_attr_2(devattr)->index;
|
||||
struct max6697_data *data = max6697_update_device(dev);
|
||||
int temp;
|
||||
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
temp = data->temp[nr][index];
|
||||
temp -= data->temp_offset;
|
||||
|
||||
return sprintf(buf, "%d\n", temp * 1000);
|
||||
}
|
||||
|
||||
static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
int index = to_sensor_dev_attr(attr)->index;
|
||||
struct max6697_data *data = max6697_update_device(dev);
|
||||
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
if (data->chip->alarm_map)
|
||||
index = data->chip->alarm_map[index];
|
||||
|
||||
return sprintf(buf, "%u\n", (data->alarms >> index) & 0x1);
|
||||
}
|
||||
|
||||
static ssize_t set_temp(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
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 max6697_data *data = i2c_get_clientdata(client);
|
||||
long temp;
|
||||
int ret;
|
||||
|
||||
ret = kstrtol(buf, 10, &temp);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
temp = DIV_ROUND_CLOSEST(temp, 1000) + data->temp_offset;
|
||||
temp = clamp_val(temp, 0, data->type == max6581 ? 255 : 127);
|
||||
data->temp[nr][index] = temp;
|
||||
ret = i2c_smbus_write_byte_data(client,
|
||||
index == 2 ? MAX6697_REG_MAX[nr]
|
||||
: MAX6697_REG_CRIT[nr],
|
||||
temp);
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
return ret < 0 ? ret : count;
|
||||
}
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0);
|
||||
static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
0, MAX6697_TEMP_MAX);
|
||||
static SENSOR_DEVICE_ATTR_2(temp1_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
0, MAX6697_TEMP_CRIT);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1);
|
||||
static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
1, MAX6697_TEMP_MAX);
|
||||
static SENSOR_DEVICE_ATTR_2(temp2_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
1, MAX6697_TEMP_CRIT);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_input, NULL, 2);
|
||||
static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
2, MAX6697_TEMP_MAX);
|
||||
static SENSOR_DEVICE_ATTR_2(temp3_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
2, MAX6697_TEMP_CRIT);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_input, NULL, 3);
|
||||
static SENSOR_DEVICE_ATTR_2(temp4_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
3, MAX6697_TEMP_MAX);
|
||||
static SENSOR_DEVICE_ATTR_2(temp4_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
3, MAX6697_TEMP_CRIT);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp_input, NULL, 4);
|
||||
static SENSOR_DEVICE_ATTR_2(temp5_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
4, MAX6697_TEMP_MAX);
|
||||
static SENSOR_DEVICE_ATTR_2(temp5_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
4, MAX6697_TEMP_CRIT);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp_input, NULL, 5);
|
||||
static SENSOR_DEVICE_ATTR_2(temp6_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
5, MAX6697_TEMP_MAX);
|
||||
static SENSOR_DEVICE_ATTR_2(temp6_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
5, MAX6697_TEMP_CRIT);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_temp_input, NULL, 6);
|
||||
static SENSOR_DEVICE_ATTR_2(temp7_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
6, MAX6697_TEMP_MAX);
|
||||
static SENSOR_DEVICE_ATTR_2(temp7_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
6, MAX6697_TEMP_CRIT);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_temp_input, NULL, 7);
|
||||
static SENSOR_DEVICE_ATTR_2(temp8_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
7, MAX6697_TEMP_MAX);
|
||||
static SENSOR_DEVICE_ATTR_2(temp8_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
|
||||
7, MAX6697_TEMP_CRIT);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 22);
|
||||
static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 16);
|
||||
static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 17);
|
||||
static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_alarm, NULL, 18);
|
||||
static SENSOR_DEVICE_ATTR(temp5_max_alarm, S_IRUGO, show_alarm, NULL, 19);
|
||||
static SENSOR_DEVICE_ATTR(temp6_max_alarm, S_IRUGO, show_alarm, NULL, 20);
|
||||
static SENSOR_DEVICE_ATTR(temp7_max_alarm, S_IRUGO, show_alarm, NULL, 21);
|
||||
static SENSOR_DEVICE_ATTR(temp8_max_alarm, S_IRUGO, show_alarm, NULL, 23);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14);
|
||||
static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 8);
|
||||
static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 9);
|
||||
static SENSOR_DEVICE_ATTR(temp4_crit_alarm, S_IRUGO, show_alarm, NULL, 10);
|
||||
static SENSOR_DEVICE_ATTR(temp5_crit_alarm, S_IRUGO, show_alarm, NULL, 11);
|
||||
static SENSOR_DEVICE_ATTR(temp6_crit_alarm, S_IRUGO, show_alarm, NULL, 12);
|
||||
static SENSOR_DEVICE_ATTR(temp7_crit_alarm, S_IRUGO, show_alarm, NULL, 13);
|
||||
static SENSOR_DEVICE_ATTR(temp8_crit_alarm, S_IRUGO, show_alarm, NULL, 15);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 1);
|
||||
static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 2);
|
||||
static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_alarm, NULL, 3);
|
||||
static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_alarm, NULL, 4);
|
||||
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 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 void max6697_get_config_of(struct device_node *node,
|
||||
struct max6697_platform_data *pdata)
|
||||
{
|
||||
int len;
|
||||
const __be32 *prop;
|
||||
|
||||
prop = of_get_property(node, "smbus-timeout-disable", &len);
|
||||
if (prop)
|
||||
pdata->smbus_timeout_disable = true;
|
||||
prop = of_get_property(node, "extended-range-enable", &len);
|
||||
if (prop)
|
||||
pdata->extended_range_enable = true;
|
||||
prop = of_get_property(node, "beta-compensation-enable", &len);
|
||||
if (prop)
|
||||
pdata->beta_compensation = true;
|
||||
prop = of_get_property(node, "alert-mask", &len);
|
||||
if (prop && len == sizeof(u32))
|
||||
pdata->alert_mask = be32_to_cpu(prop[0]);
|
||||
prop = of_get_property(node, "over-temperature-mask", &len);
|
||||
if (prop && len == sizeof(u32))
|
||||
pdata->over_temperature_mask = be32_to_cpu(prop[0]);
|
||||
prop = of_get_property(node, "resistance-cancellation", &len);
|
||||
if (prop) {
|
||||
if (len == sizeof(u32))
|
||||
pdata->resistance_cancellation = be32_to_cpu(prop[0]);
|
||||
else
|
||||
pdata->resistance_cancellation = 0xfe;
|
||||
}
|
||||
prop = of_get_property(node, "transistor-ideality", &len);
|
||||
if (prop && len == 2 * sizeof(u32)) {
|
||||
pdata->ideality_mask = be32_to_cpu(prop[0]);
|
||||
pdata->ideality_value = be32_to_cpu(prop[1]);
|
||||
}
|
||||
}
|
||||
|
||||
static int max6697_init_chip(struct i2c_client *client)
|
||||
{
|
||||
struct max6697_data *data = i2c_get_clientdata(client);
|
||||
struct max6697_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||
struct max6697_platform_data p;
|
||||
const struct max6697_chip_data *chip = data->chip;
|
||||
int factor = chip->channels;
|
||||
int ret, reg;
|
||||
|
||||
/*
|
||||
* Don't touch configuration if neither platform data nor OF
|
||||
* configuration was specified. If that is the case, use the
|
||||
* current chip configuration.
|
||||
*/
|
||||
if (!pdata && !client->dev.of_node) {
|
||||
reg = i2c_smbus_read_byte_data(client, MAX6697_REG_CONFIG);
|
||||
if (reg < 0)
|
||||
return reg;
|
||||
if (data->type == max6581) {
|
||||
if (reg & MAX6581_CONF_EXTENDED)
|
||||
data->temp_offset = 64;
|
||||
reg = i2c_smbus_read_byte_data(client,
|
||||
MAX6581_REG_RESISTANCE);
|
||||
if (reg < 0)
|
||||
return reg;
|
||||
factor += hweight8(reg);
|
||||
} else {
|
||||
if (reg & MAX6697_CONF_RESISTANCE)
|
||||
factor++;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (client->dev.of_node) {
|
||||
memset(&p, 0, sizeof(p));
|
||||
max6697_get_config_of(client->dev.of_node, &p);
|
||||
pdata = &p;
|
||||
}
|
||||
|
||||
reg = 0;
|
||||
if (pdata->smbus_timeout_disable &&
|
||||
(chip->valid_conf & MAX6697_CONF_TIMEOUT)) {
|
||||
reg |= MAX6697_CONF_TIMEOUT;
|
||||
}
|
||||
if (pdata->extended_range_enable &&
|
||||
(chip->valid_conf & MAX6581_CONF_EXTENDED)) {
|
||||
reg |= MAX6581_CONF_EXTENDED;
|
||||
data->temp_offset = 64;
|
||||
}
|
||||
if (pdata->resistance_cancellation &&
|
||||
(chip->valid_conf & MAX6697_CONF_RESISTANCE)) {
|
||||
reg |= MAX6697_CONF_RESISTANCE;
|
||||
factor++;
|
||||
}
|
||||
if (pdata->beta_compensation &&
|
||||
(chip->valid_conf & MAX6693_CONF_BETA)) {
|
||||
reg |= MAX6693_CONF_BETA;
|
||||
}
|
||||
|
||||
ret = i2c_smbus_write_byte_data(client, MAX6697_REG_CONFIG, reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = i2c_smbus_write_byte_data(client, MAX6697_REG_ALERT_MASK,
|
||||
MAX6697_MAP_BITS(pdata->alert_mask));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = i2c_smbus_write_byte_data(client, MAX6697_REG_OVERT_MASK,
|
||||
MAX6697_MAP_BITS(pdata->over_temperature_mask));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (data->type == max6581) {
|
||||
factor += hweight8(pdata->resistance_cancellation >> 1);
|
||||
ret = i2c_smbus_write_byte_data(client, MAX6581_REG_RESISTANCE,
|
||||
pdata->resistance_cancellation >> 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = i2c_smbus_write_byte_data(client, MAX6581_REG_IDEALITY,
|
||||
pdata->ideality_mask >> 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = i2c_smbus_write_byte_data(client,
|
||||
MAX6581_REG_IDEALITY_SELECT,
|
||||
pdata->ideality_value);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
done:
|
||||
data->update_interval = factor * MAX6697_CONV_TIME;
|
||||
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;
|
||||
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
return -ENODEV;
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(struct max6697_data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->type = id->driver_data;
|
||||
data->chip = &max6697_chip_data[data->type];
|
||||
|
||||
i2c_set_clientdata(client, data);
|
||||
mutex_init(&data->update_lock);
|
||||
|
||||
err = max6697_init_chip(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;
|
||||
}
|
||||
}
|
||||
|
||||
data->hwmon_dev = hwmon_device_register(dev);
|
||||
if (IS_ERR(data->hwmon_dev)) {
|
||||
err = PTR_ERR(data->hwmon_dev);
|
||||
goto error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
max6697_remove_files(client);
|
||||
return err;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id max6697_id[] = {
|
||||
{ "max6581", max6581 },
|
||||
{ "max6602", max6602 },
|
||||
{ "max6622", max6622 },
|
||||
{ "max6636", max6636 },
|
||||
{ "max6689", max6689 },
|
||||
{ "max6693", max6693 },
|
||||
{ "max6694", max6694 },
|
||||
{ "max6697", max6697 },
|
||||
{ "max6698", max6698 },
|
||||
{ "max6699", max6699 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, max6697_id);
|
||||
|
||||
static struct i2c_driver max6697_driver = {
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.driver = {
|
||||
.name = "max6697",
|
||||
},
|
||||
.probe = max6697_probe,
|
||||
.remove = max6697_remove,
|
||||
.id_table = max6697_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(max6697_driver);
|
||||
|
||||
MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
|
||||
MODULE_DESCRIPTION("MAX6697 temperature sensor driver");
|
||||
MODULE_LICENSE("GPL");
|
@@ -43,7 +43,7 @@ struct ntc_compensation {
|
||||
* The following compensation tables are from the specification of Murata NTC
|
||||
* Thermistors Datasheet
|
||||
*/
|
||||
const struct ntc_compensation ncpXXwb473[] = {
|
||||
static const struct ntc_compensation ncpXXwb473[] = {
|
||||
{ .temp_C = -40, .ohm = 1747920 },
|
||||
{ .temp_C = -35, .ohm = 1245428 },
|
||||
{ .temp_C = -30, .ohm = 898485 },
|
||||
@@ -79,7 +79,7 @@ const struct ntc_compensation ncpXXwb473[] = {
|
||||
{ .temp_C = 120, .ohm = 1615 },
|
||||
{ .temp_C = 125, .ohm = 1406 },
|
||||
};
|
||||
const struct ntc_compensation ncpXXwl333[] = {
|
||||
static const struct ntc_compensation ncpXXwl333[] = {
|
||||
{ .temp_C = -40, .ohm = 1610154 },
|
||||
{ .temp_C = -35, .ohm = 1130850 },
|
||||
{ .temp_C = -30, .ohm = 802609 },
|
||||
|
@@ -72,7 +72,7 @@ config SENSORS_MAX34440
|
||||
default n
|
||||
help
|
||||
If you say yes here you get hardware monitoring support for Maxim
|
||||
MAX34440, MAX34441, and MAX34446.
|
||||
MAX34440, MAX34441, MAX34446, MAX34460, and MAX34461.
|
||||
|
||||
This driver can also be built as a module. If so, the module will
|
||||
be called max34440.
|
||||
|
@@ -2,6 +2,7 @@
|
||||
* Hardware monitoring driver for Maxim MAX34440/MAX34441
|
||||
*
|
||||
* Copyright (c) 2011 Ericsson AB.
|
||||
* Copyright (c) 2012 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
|
||||
@@ -25,7 +26,7 @@
|
||||
#include <linux/i2c.h>
|
||||
#include "pmbus.h"
|
||||
|
||||
enum chips { max34440, max34441, max34446 };
|
||||
enum chips { max34440, max34441, max34446, max34460, max34461 };
|
||||
|
||||
#define MAX34440_MFR_VOUT_PEAK 0xd4
|
||||
#define MAX34440_MFR_IOUT_PEAK 0xd5
|
||||
@@ -87,7 +88,8 @@ static int max34440_read_word_data(struct i2c_client *client, int page, int reg)
|
||||
MAX34446_MFR_POUT_PEAK);
|
||||
break;
|
||||
case PMBUS_VIRT_READ_TEMP_AVG:
|
||||
if (data->id != max34446)
|
||||
if (data->id != max34446 && data->id != max34460 &&
|
||||
data->id != max34461)
|
||||
return -ENXIO;
|
||||
ret = pmbus_read_word_data(client, page,
|
||||
MAX34446_MFR_TEMPERATURE_AVG);
|
||||
@@ -322,6 +324,73 @@ static struct pmbus_driver_info max34440_info[] = {
|
||||
.read_word_data = max34440_read_word_data,
|
||||
.write_word_data = max34440_write_word_data,
|
||||
},
|
||||
[max34460] = {
|
||||
.pages = 18,
|
||||
.format[PSC_VOLTAGE_OUT] = direct,
|
||||
.format[PSC_TEMPERATURE] = direct,
|
||||
.m[PSC_VOLTAGE_OUT] = 1,
|
||||
.b[PSC_VOLTAGE_OUT] = 0,
|
||||
.R[PSC_VOLTAGE_OUT] = 3,
|
||||
.m[PSC_TEMPERATURE] = 1,
|
||||
.b[PSC_TEMPERATURE] = 0,
|
||||
.R[PSC_TEMPERATURE] = 2,
|
||||
.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
.func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
.func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
.func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
.func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
.func[5] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
.func[6] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
.func[7] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
.func[8] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
.func[9] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
.func[10] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
.func[11] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
.func[13] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
|
||||
.func[14] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
|
||||
.func[15] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
|
||||
.func[16] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
|
||||
.func[17] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
|
||||
.read_byte_data = max34440_read_byte_data,
|
||||
.read_word_data = max34440_read_word_data,
|
||||
.write_word_data = max34440_write_word_data,
|
||||
},
|
||||
[max34461] = {
|
||||
.pages = 23,
|
||||
.format[PSC_VOLTAGE_OUT] = direct,
|
||||
.format[PSC_TEMPERATURE] = direct,
|
||||
.m[PSC_VOLTAGE_OUT] = 1,
|
||||
.b[PSC_VOLTAGE_OUT] = 0,
|
||||
.R[PSC_VOLTAGE_OUT] = 3,
|
||||
.m[PSC_TEMPERATURE] = 1,
|
||||
.b[PSC_TEMPERATURE] = 0,
|
||||
.R[PSC_TEMPERATURE] = 2,
|
||||
.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
.func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
.func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
.func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
.func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
.func[5] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
.func[6] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
.func[7] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
.func[8] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
.func[9] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
.func[10] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
.func[11] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
.func[12] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
.func[13] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
.func[14] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
.func[15] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
|
||||
/* page 16 is reserved */
|
||||
.func[17] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
|
||||
.func[18] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
|
||||
.func[19] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
|
||||
.func[20] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
|
||||
.func[21] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
|
||||
.read_byte_data = max34440_read_byte_data,
|
||||
.read_word_data = max34440_read_word_data,
|
||||
.write_word_data = max34440_write_word_data,
|
||||
},
|
||||
};
|
||||
|
||||
static int max34440_probe(struct i2c_client *client,
|
||||
@@ -343,6 +412,8 @@ static const struct i2c_device_id max34440_id[] = {
|
||||
{"max34440", max34440},
|
||||
{"max34441", max34441},
|
||||
{"max34446", max34446},
|
||||
{"max34460", max34460},
|
||||
{"max34461", max34461},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, max34440_id);
|
||||
|
@@ -2,6 +2,7 @@
|
||||
* pmbus.h - Common defines and structures for PMBus devices
|
||||
*
|
||||
* Copyright (c) 2010, 2011 Ericsson AB.
|
||||
* Copyright (c) 2012 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
|
||||
@@ -177,6 +178,13 @@
|
||||
#define PMBUS_VIRT_READ_TEMP2_MAX (PMBUS_VIRT_BASE + 28)
|
||||
#define PMBUS_VIRT_RESET_TEMP2_HISTORY (PMBUS_VIRT_BASE + 29)
|
||||
|
||||
#define PMBUS_VIRT_READ_VMON (PMBUS_VIRT_BASE + 30)
|
||||
#define PMBUS_VIRT_VMON_UV_WARN_LIMIT (PMBUS_VIRT_BASE + 31)
|
||||
#define PMBUS_VIRT_VMON_OV_WARN_LIMIT (PMBUS_VIRT_BASE + 32)
|
||||
#define PMBUS_VIRT_VMON_UV_FAULT_LIMIT (PMBUS_VIRT_BASE + 33)
|
||||
#define PMBUS_VIRT_VMON_OV_FAULT_LIMIT (PMBUS_VIRT_BASE + 34)
|
||||
#define PMBUS_VIRT_STATUS_VMON (PMBUS_VIRT_BASE + 35)
|
||||
|
||||
/*
|
||||
* CAPABILITY
|
||||
*/
|
||||
@@ -317,6 +325,8 @@ enum pmbus_sensor_classes {
|
||||
#define PMBUS_HAVE_STATUS_TEMP (1 << 15)
|
||||
#define PMBUS_HAVE_STATUS_FAN12 (1 << 16)
|
||||
#define PMBUS_HAVE_STATUS_FAN34 (1 << 17)
|
||||
#define PMBUS_HAVE_VMON (1 << 18)
|
||||
#define PMBUS_HAVE_STATUS_VMON (1 << 19)
|
||||
|
||||
enum pmbus_data_format { linear = 0, direct, vid };
|
||||
|
||||
@@ -359,6 +369,7 @@ struct pmbus_driver_info {
|
||||
|
||||
/* Function declarations */
|
||||
|
||||
void pmbus_clear_cache(struct i2c_client *client);
|
||||
int pmbus_set_page(struct i2c_client *client, u8 page);
|
||||
int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg);
|
||||
int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word);
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,7 @@
|
||||
* Hardware monitoring driver for ZL6100 and compatibles
|
||||
*
|
||||
* Copyright (c) 2011 Ericsson AB.
|
||||
* Copyright (c) 2012 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
|
||||
@@ -45,12 +46,87 @@ struct zl6100_data {
|
||||
|
||||
#define ZL6100_MFR_XTEMP_ENABLE (1 << 7)
|
||||
|
||||
#define MFR_VMON_OV_FAULT_LIMIT 0xf5
|
||||
#define MFR_VMON_UV_FAULT_LIMIT 0xf6
|
||||
#define MFR_READ_VMON 0xf7
|
||||
|
||||
#define VMON_UV_WARNING (1 << 5)
|
||||
#define VMON_OV_WARNING (1 << 4)
|
||||
#define VMON_UV_FAULT (1 << 1)
|
||||
#define VMON_OV_FAULT (1 << 0)
|
||||
|
||||
#define ZL6100_WAIT_TIME 1000 /* uS */
|
||||
|
||||
static ushort delay = ZL6100_WAIT_TIME;
|
||||
module_param(delay, ushort, 0644);
|
||||
MODULE_PARM_DESC(delay, "Delay between chip accesses in uS");
|
||||
|
||||
/* Convert linear sensor value to milli-units */
|
||||
static long zl6100_l2d(s16 l)
|
||||
{
|
||||
s16 exponent;
|
||||
s32 mantissa;
|
||||
long val;
|
||||
|
||||
exponent = l >> 11;
|
||||
mantissa = ((s16)((l & 0x7ff) << 5)) >> 5;
|
||||
|
||||
val = mantissa;
|
||||
|
||||
/* scale result to milli-units */
|
||||
val = val * 1000L;
|
||||
|
||||
if (exponent >= 0)
|
||||
val <<= exponent;
|
||||
else
|
||||
val >>= -exponent;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
#define MAX_MANTISSA (1023 * 1000)
|
||||
#define MIN_MANTISSA (511 * 1000)
|
||||
|
||||
static u16 zl6100_d2l(long val)
|
||||
{
|
||||
s16 exponent = 0, mantissa;
|
||||
bool negative = false;
|
||||
|
||||
/* simple case */
|
||||
if (val == 0)
|
||||
return 0;
|
||||
|
||||
if (val < 0) {
|
||||
negative = true;
|
||||
val = -val;
|
||||
}
|
||||
|
||||
/* Reduce large mantissa until it fits into 10 bit */
|
||||
while (val >= MAX_MANTISSA && exponent < 15) {
|
||||
exponent++;
|
||||
val >>= 1;
|
||||
}
|
||||
/* Increase small mantissa to improve precision */
|
||||
while (val < MIN_MANTISSA && exponent > -15) {
|
||||
exponent--;
|
||||
val <<= 1;
|
||||
}
|
||||
|
||||
/* Convert mantissa from milli-units to units */
|
||||
mantissa = DIV_ROUND_CLOSEST(val, 1000);
|
||||
|
||||
/* Ensure that resulting number is within range */
|
||||
if (mantissa > 0x3ff)
|
||||
mantissa = 0x3ff;
|
||||
|
||||
/* restore sign */
|
||||
if (negative)
|
||||
mantissa = -mantissa;
|
||||
|
||||
/* Convert to 5 bit exponent, 11 bit mantissa */
|
||||
return (mantissa & 0x7ff) | ((exponent << 11) & 0xf800);
|
||||
}
|
||||
|
||||
/* Some chips need a delay between accesses */
|
||||
static inline void zl6100_wait(const struct zl6100_data *data)
|
||||
{
|
||||
@@ -65,9 +141,9 @@ static int zl6100_read_word_data(struct i2c_client *client, int page, int reg)
|
||||
{
|
||||
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
|
||||
struct zl6100_data *data = to_zl6100_data(info);
|
||||
int ret;
|
||||
int ret, vreg;
|
||||
|
||||
if (page || reg >= PMBUS_VIRT_BASE)
|
||||
if (page > 0)
|
||||
return -ENXIO;
|
||||
|
||||
if (data->id == zl2005) {
|
||||
@@ -83,9 +159,39 @@ static int zl6100_read_word_data(struct i2c_client *client, int page, int reg)
|
||||
}
|
||||
}
|
||||
|
||||
switch (reg) {
|
||||
case PMBUS_VIRT_READ_VMON:
|
||||
vreg = MFR_READ_VMON;
|
||||
break;
|
||||
case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
|
||||
case PMBUS_VIRT_VMON_OV_FAULT_LIMIT:
|
||||
vreg = MFR_VMON_OV_FAULT_LIMIT;
|
||||
break;
|
||||
case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
|
||||
case PMBUS_VIRT_VMON_UV_FAULT_LIMIT:
|
||||
vreg = MFR_VMON_UV_FAULT_LIMIT;
|
||||
break;
|
||||
default:
|
||||
if (reg >= PMBUS_VIRT_BASE)
|
||||
return -ENXIO;
|
||||
vreg = reg;
|
||||
break;
|
||||
}
|
||||
|
||||
zl6100_wait(data);
|
||||
ret = pmbus_read_word_data(client, page, reg);
|
||||
ret = pmbus_read_word_data(client, page, vreg);
|
||||
data->access = ktime_get();
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
switch (reg) {
|
||||
case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
|
||||
ret = zl6100_d2l(DIV_ROUND_CLOSEST(zl6100_l2d(ret) * 9, 10));
|
||||
break;
|
||||
case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
|
||||
ret = zl6100_d2l(DIV_ROUND_CLOSEST(zl6100_l2d(ret) * 11, 10));
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -94,13 +200,35 @@ static int zl6100_read_byte_data(struct i2c_client *client, int page, int reg)
|
||||
{
|
||||
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
|
||||
struct zl6100_data *data = to_zl6100_data(info);
|
||||
int ret;
|
||||
int ret, status;
|
||||
|
||||
if (page > 0)
|
||||
return -ENXIO;
|
||||
|
||||
zl6100_wait(data);
|
||||
ret = pmbus_read_byte_data(client, page, reg);
|
||||
|
||||
switch (reg) {
|
||||
case PMBUS_VIRT_STATUS_VMON:
|
||||
ret = pmbus_read_byte_data(client, 0,
|
||||
PMBUS_STATUS_MFR_SPECIFIC);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
status = 0;
|
||||
if (ret & VMON_UV_WARNING)
|
||||
status |= PB_VOLTAGE_UV_WARNING;
|
||||
if (ret & VMON_OV_WARNING)
|
||||
status |= PB_VOLTAGE_OV_WARNING;
|
||||
if (ret & VMON_UV_FAULT)
|
||||
status |= PB_VOLTAGE_UV_FAULT;
|
||||
if (ret & VMON_OV_FAULT)
|
||||
status |= PB_VOLTAGE_OV_FAULT;
|
||||
ret = status;
|
||||
break;
|
||||
default:
|
||||
ret = pmbus_read_byte_data(client, page, reg);
|
||||
break;
|
||||
}
|
||||
data->access = ktime_get();
|
||||
|
||||
return ret;
|
||||
@@ -111,13 +239,38 @@ static int zl6100_write_word_data(struct i2c_client *client, int page, int reg,
|
||||
{
|
||||
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
|
||||
struct zl6100_data *data = to_zl6100_data(info);
|
||||
int ret;
|
||||
int ret, vreg;
|
||||
|
||||
if (page || reg >= PMBUS_VIRT_BASE)
|
||||
if (page > 0)
|
||||
return -ENXIO;
|
||||
|
||||
switch (reg) {
|
||||
case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
|
||||
word = zl6100_d2l(DIV_ROUND_CLOSEST(zl6100_l2d(word) * 10, 9));
|
||||
vreg = MFR_VMON_OV_FAULT_LIMIT;
|
||||
pmbus_clear_cache(client);
|
||||
break;
|
||||
case PMBUS_VIRT_VMON_OV_FAULT_LIMIT:
|
||||
vreg = MFR_VMON_OV_FAULT_LIMIT;
|
||||
pmbus_clear_cache(client);
|
||||
break;
|
||||
case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
|
||||
word = zl6100_d2l(DIV_ROUND_CLOSEST(zl6100_l2d(word) * 10, 11));
|
||||
vreg = MFR_VMON_UV_FAULT_LIMIT;
|
||||
pmbus_clear_cache(client);
|
||||
break;
|
||||
case PMBUS_VIRT_VMON_UV_FAULT_LIMIT:
|
||||
vreg = MFR_VMON_UV_FAULT_LIMIT;
|
||||
pmbus_clear_cache(client);
|
||||
break;
|
||||
default:
|
||||
if (reg >= PMBUS_VIRT_BASE)
|
||||
return -ENXIO;
|
||||
vreg = reg;
|
||||
}
|
||||
|
||||
zl6100_wait(data);
|
||||
ret = pmbus_write_word_data(client, page, reg, word);
|
||||
ret = pmbus_write_word_data(client, page, vreg, word);
|
||||
data->access = ktime_get();
|
||||
|
||||
return ret;
|
||||
@@ -225,6 +378,13 @@ static int zl6100_probe(struct i2c_client *client,
|
||||
| PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
|
||||
| PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
|
||||
|
||||
/*
|
||||
* ZL2004, ZL9101M, and ZL9117M support monitoring an extra voltage
|
||||
* (VMON for ZL2004, VDRV for ZL9101M and ZL9117M). Report it as vmon.
|
||||
*/
|
||||
if (data->id == zl2004 || data->id == zl9101 || data->id == zl9117)
|
||||
info->func[0] |= PMBUS_HAVE_VMON | PMBUS_HAVE_STATUS_VMON;
|
||||
|
||||
ret = i2c_smbus_read_word_data(client, ZL6100_MFR_CONFIG);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
@@ -139,12 +139,12 @@ static const u8 sht15_crc8_table[] = {
|
||||
* @reg: associated regulator (if specified).
|
||||
* @nb: notifier block to handle notifications of voltage
|
||||
* changes.
|
||||
* @supply_uV: local copy of supply voltage used to allow use of
|
||||
* @supply_uv: local copy of supply voltage used to allow use of
|
||||
* regulator consumer if available.
|
||||
* @supply_uV_valid: indicates that an updated value has not yet been
|
||||
* @supply_uv_valid: indicates that an updated value has not yet been
|
||||
* obtained from the regulator and so any calculations
|
||||
* based upon it will be invalid.
|
||||
* @update_supply_work: work struct that is used to update the supply_uV.
|
||||
* @update_supply_work: work struct that is used to update the supply_uv.
|
||||
* @interrupt_handled: flag used to indicate a handler has been scheduled.
|
||||
*/
|
||||
struct sht15_data {
|
||||
@@ -166,8 +166,8 @@ struct sht15_data {
|
||||
struct device *hwmon_dev;
|
||||
struct regulator *reg;
|
||||
struct notifier_block nb;
|
||||
int supply_uV;
|
||||
bool supply_uV_valid;
|
||||
int supply_uv;
|
||||
bool supply_uv_valid;
|
||||
struct work_struct update_supply_work;
|
||||
atomic_t interrupt_handled;
|
||||
};
|
||||
@@ -212,11 +212,13 @@ static u8 sht15_crc8(struct sht15_data *data,
|
||||
*
|
||||
* This implements section 3.4 of the data sheet
|
||||
*/
|
||||
static void sht15_connection_reset(struct sht15_data *data)
|
||||
static int sht15_connection_reset(struct sht15_data *data)
|
||||
{
|
||||
int i;
|
||||
int i, err;
|
||||
|
||||
gpio_direction_output(data->pdata->gpio_data, 1);
|
||||
err = gpio_direction_output(data->pdata->gpio_data, 1);
|
||||
if (err)
|
||||
return err;
|
||||
ndelay(SHT15_TSCKL);
|
||||
gpio_set_value(data->pdata->gpio_sck, 0);
|
||||
ndelay(SHT15_TSCKL);
|
||||
@@ -226,6 +228,7 @@ static void sht15_connection_reset(struct sht15_data *data)
|
||||
gpio_set_value(data->pdata->gpio_sck, 0);
|
||||
ndelay(SHT15_TSCKL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -251,10 +254,14 @@ static inline void sht15_send_bit(struct sht15_data *data, int val)
|
||||
* conservative ones used in implementation. This implements
|
||||
* figure 12 on the data sheet.
|
||||
*/
|
||||
static void sht15_transmission_start(struct sht15_data *data)
|
||||
static int sht15_transmission_start(struct sht15_data *data)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* ensure data is high and output */
|
||||
gpio_direction_output(data->pdata->gpio_data, 1);
|
||||
err = gpio_direction_output(data->pdata->gpio_data, 1);
|
||||
if (err)
|
||||
return err;
|
||||
ndelay(SHT15_TSU);
|
||||
gpio_set_value(data->pdata->gpio_sck, 0);
|
||||
ndelay(SHT15_TSCKL);
|
||||
@@ -270,6 +277,7 @@ static void sht15_transmission_start(struct sht15_data *data)
|
||||
ndelay(SHT15_TSU);
|
||||
gpio_set_value(data->pdata->gpio_sck, 0);
|
||||
ndelay(SHT15_TSCKL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -293,13 +301,19 @@ static void sht15_send_byte(struct sht15_data *data, u8 byte)
|
||||
*/
|
||||
static int sht15_wait_for_response(struct sht15_data *data)
|
||||
{
|
||||
gpio_direction_input(data->pdata->gpio_data);
|
||||
int err;
|
||||
|
||||
err = gpio_direction_input(data->pdata->gpio_data);
|
||||
if (err)
|
||||
return err;
|
||||
gpio_set_value(data->pdata->gpio_sck, 1);
|
||||
ndelay(SHT15_TSCKH);
|
||||
if (gpio_get_value(data->pdata->gpio_data)) {
|
||||
gpio_set_value(data->pdata->gpio_sck, 0);
|
||||
dev_err(data->dev, "Command not acknowledged\n");
|
||||
sht15_connection_reset(data);
|
||||
err = sht15_connection_reset(data);
|
||||
if (err)
|
||||
return err;
|
||||
return -EIO;
|
||||
}
|
||||
gpio_set_value(data->pdata->gpio_sck, 0);
|
||||
@@ -317,12 +331,13 @@ static int sht15_wait_for_response(struct sht15_data *data)
|
||||
*/
|
||||
static int sht15_send_cmd(struct sht15_data *data, u8 cmd)
|
||||
{
|
||||
int ret = 0;
|
||||
int err;
|
||||
|
||||
sht15_transmission_start(data);
|
||||
err = sht15_transmission_start(data);
|
||||
if (err)
|
||||
return err;
|
||||
sht15_send_byte(data, cmd);
|
||||
ret = sht15_wait_for_response(data);
|
||||
return ret;
|
||||
return sht15_wait_for_response(data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -352,9 +367,13 @@ static int sht15_soft_reset(struct sht15_data *data)
|
||||
* Each byte of data is acknowledged by pulling the data line
|
||||
* low for one clock pulse.
|
||||
*/
|
||||
static void sht15_ack(struct sht15_data *data)
|
||||
static int sht15_ack(struct sht15_data *data)
|
||||
{
|
||||
gpio_direction_output(data->pdata->gpio_data, 0);
|
||||
int err;
|
||||
|
||||
err = gpio_direction_output(data->pdata->gpio_data, 0);
|
||||
if (err)
|
||||
return err;
|
||||
ndelay(SHT15_TSU);
|
||||
gpio_set_value(data->pdata->gpio_sck, 1);
|
||||
ndelay(SHT15_TSU);
|
||||
@@ -362,7 +381,7 @@ static void sht15_ack(struct sht15_data *data)
|
||||
ndelay(SHT15_TSU);
|
||||
gpio_set_value(data->pdata->gpio_data, 1);
|
||||
|
||||
gpio_direction_input(data->pdata->gpio_data);
|
||||
return gpio_direction_input(data->pdata->gpio_data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -371,14 +390,19 @@ static void sht15_ack(struct sht15_data *data)
|
||||
*
|
||||
* This is basically a NAK (single clock pulse, data high).
|
||||
*/
|
||||
static void sht15_end_transmission(struct sht15_data *data)
|
||||
static int sht15_end_transmission(struct sht15_data *data)
|
||||
{
|
||||
gpio_direction_output(data->pdata->gpio_data, 1);
|
||||
int err;
|
||||
|
||||
err = gpio_direction_output(data->pdata->gpio_data, 1);
|
||||
if (err)
|
||||
return err;
|
||||
ndelay(SHT15_TSU);
|
||||
gpio_set_value(data->pdata->gpio_sck, 1);
|
||||
ndelay(SHT15_TSCKH);
|
||||
gpio_set_value(data->pdata->gpio_sck, 0);
|
||||
ndelay(SHT15_TSCKL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -410,17 +434,19 @@ static u8 sht15_read_byte(struct sht15_data *data)
|
||||
*/
|
||||
static int sht15_send_status(struct sht15_data *data, u8 status)
|
||||
{
|
||||
int ret;
|
||||
int err;
|
||||
|
||||
ret = sht15_send_cmd(data, SHT15_WRITE_STATUS);
|
||||
if (ret)
|
||||
return ret;
|
||||
gpio_direction_output(data->pdata->gpio_data, 1);
|
||||
err = sht15_send_cmd(data, SHT15_WRITE_STATUS);
|
||||
if (err)
|
||||
return err;
|
||||
err = gpio_direction_output(data->pdata->gpio_data, 1);
|
||||
if (err)
|
||||
return err;
|
||||
ndelay(SHT15_TSU);
|
||||
sht15_send_byte(data, status);
|
||||
ret = sht15_wait_for_response(data);
|
||||
if (ret)
|
||||
return ret;
|
||||
err = sht15_wait_for_response(data);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
data->val_status = status;
|
||||
return 0;
|
||||
@@ -446,7 +472,7 @@ static int sht15_update_status(struct sht15_data *data)
|
||||
|| !data->status_valid) {
|
||||
ret = sht15_send_cmd(data, SHT15_READ_STATUS);
|
||||
if (ret)
|
||||
goto error_ret;
|
||||
goto unlock;
|
||||
status = sht15_read_byte(data);
|
||||
|
||||
if (data->checksumming) {
|
||||
@@ -458,7 +484,9 @@ static int sht15_update_status(struct sht15_data *data)
|
||||
== dev_checksum);
|
||||
}
|
||||
|
||||
sht15_end_transmission(data);
|
||||
ret = sht15_end_transmission(data);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
/*
|
||||
* Perform checksum validation on the received data.
|
||||
@@ -469,27 +497,27 @@ static int sht15_update_status(struct sht15_data *data)
|
||||
previous_config = data->val_status & 0x07;
|
||||
ret = sht15_soft_reset(data);
|
||||
if (ret)
|
||||
goto error_ret;
|
||||
goto unlock;
|
||||
if (previous_config) {
|
||||
ret = sht15_send_status(data, previous_config);
|
||||
if (ret) {
|
||||
dev_err(data->dev,
|
||||
"CRC validation failed, unable "
|
||||
"to restore device settings\n");
|
||||
goto error_ret;
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
ret = -EAGAIN;
|
||||
goto error_ret;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
data->val_status = status;
|
||||
data->status_valid = true;
|
||||
data->last_status = jiffies;
|
||||
}
|
||||
error_ret:
|
||||
mutex_unlock(&data->read_lock);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&data->read_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -511,7 +539,9 @@ static int sht15_measurement(struct sht15_data *data,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
gpio_direction_input(data->pdata->gpio_data);
|
||||
ret = gpio_direction_input(data->pdata->gpio_data);
|
||||
if (ret)
|
||||
return ret;
|
||||
atomic_set(&data->interrupt_handled, 0);
|
||||
|
||||
enable_irq(gpio_to_irq(data->pdata->gpio_data));
|
||||
@@ -524,9 +554,14 @@ static int sht15_measurement(struct sht15_data *data,
|
||||
ret = wait_event_timeout(data->wait_queue,
|
||||
(data->state == SHT15_READING_NOTHING),
|
||||
msecs_to_jiffies(timeout_msecs));
|
||||
if (ret == 0) {/* timeout occurred */
|
||||
if (data->state != SHT15_READING_NOTHING) { /* I/O error occurred */
|
||||
data->state = SHT15_READING_NOTHING;
|
||||
return -EIO;
|
||||
} else if (ret == 0) { /* timeout occurred */
|
||||
disable_irq_nosync(gpio_to_irq(data->pdata->gpio_data));
|
||||
sht15_connection_reset(data);
|
||||
ret = sht15_connection_reset(data);
|
||||
if (ret)
|
||||
return ret;
|
||||
return -ETIME;
|
||||
}
|
||||
|
||||
@@ -570,17 +605,17 @@ static int sht15_update_measurements(struct sht15_data *data)
|
||||
data->state = SHT15_READING_HUMID;
|
||||
ret = sht15_measurement(data, SHT15_MEASURE_RH, 160);
|
||||
if (ret)
|
||||
goto error_ret;
|
||||
goto unlock;
|
||||
data->state = SHT15_READING_TEMP;
|
||||
ret = sht15_measurement(data, SHT15_MEASURE_TEMP, 400);
|
||||
if (ret)
|
||||
goto error_ret;
|
||||
goto unlock;
|
||||
data->measurements_valid = true;
|
||||
data->last_measurement = jiffies;
|
||||
}
|
||||
error_ret:
|
||||
mutex_unlock(&data->read_lock);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&data->read_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -598,8 +633,8 @@ static inline int sht15_calc_temp(struct sht15_data *data)
|
||||
|
||||
for (i = ARRAY_SIZE(temppoints) - 1; i > 0; i--)
|
||||
/* Find pointer to interpolate */
|
||||
if (data->supply_uV > temppoints[i - 1].vdd) {
|
||||
d1 = (data->supply_uV - temppoints[i - 1].vdd)
|
||||
if (data->supply_uv > temppoints[i - 1].vdd) {
|
||||
d1 = (data->supply_uv - temppoints[i - 1].vdd)
|
||||
* (temppoints[i].d1 - temppoints[i - 1].d1)
|
||||
/ (temppoints[i].vdd - temppoints[i - 1].vdd)
|
||||
+ temppoints[i - 1].d1;
|
||||
@@ -818,7 +853,8 @@ static void sht15_bh_read_data(struct work_struct *work_s)
|
||||
/* Read the data back from the device */
|
||||
val = sht15_read_byte(data);
|
||||
val <<= 8;
|
||||
sht15_ack(data);
|
||||
if (sht15_ack(data))
|
||||
goto wakeup;
|
||||
val |= sht15_read_byte(data);
|
||||
|
||||
if (data->checksumming) {
|
||||
@@ -826,7 +862,8 @@ static void sht15_bh_read_data(struct work_struct *work_s)
|
||||
* Ask the device for a checksum and read it back.
|
||||
* Note: the device sends the checksum byte reversed.
|
||||
*/
|
||||
sht15_ack(data);
|
||||
if (sht15_ack(data))
|
||||
goto wakeup;
|
||||
dev_checksum = sht15_reverse(sht15_read_byte(data));
|
||||
checksum_vals[0] = (data->state == SHT15_READING_TEMP) ?
|
||||
SHT15_MEASURE_TEMP : SHT15_MEASURE_RH;
|
||||
@@ -837,7 +874,8 @@ static void sht15_bh_read_data(struct work_struct *work_s)
|
||||
}
|
||||
|
||||
/* Tell the device we are done */
|
||||
sht15_end_transmission(data);
|
||||
if (sht15_end_transmission(data))
|
||||
goto wakeup;
|
||||
|
||||
switch (data->state) {
|
||||
case SHT15_READING_TEMP:
|
||||
@@ -851,6 +889,7 @@ static void sht15_bh_read_data(struct work_struct *work_s)
|
||||
}
|
||||
|
||||
data->state = SHT15_READING_NOTHING;
|
||||
wakeup:
|
||||
wake_up(&data->wait_queue);
|
||||
}
|
||||
|
||||
@@ -859,7 +898,7 @@ static void sht15_update_voltage(struct work_struct *work_s)
|
||||
struct sht15_data *data
|
||||
= container_of(work_s, struct sht15_data,
|
||||
update_supply_work);
|
||||
data->supply_uV = regulator_get_voltage(data->reg);
|
||||
data->supply_uv = regulator_get_voltage(data->reg);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -878,7 +917,7 @@ static int sht15_invalidate_voltage(struct notifier_block *nb,
|
||||
struct sht15_data *data = container_of(nb, struct sht15_data, nb);
|
||||
|
||||
if (event == REGULATOR_EVENT_VOLTAGE_CHANGE)
|
||||
data->supply_uV_valid = false;
|
||||
data->supply_uv_valid = false;
|
||||
schedule_work(&data->update_supply_work);
|
||||
|
||||
return NOTIFY_OK;
|
||||
@@ -906,7 +945,7 @@ static int sht15_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
data->pdata = pdev->dev.platform_data;
|
||||
data->supply_uV = data->pdata->supply_mv * 1000;
|
||||
data->supply_uv = data->pdata->supply_mv * 1000;
|
||||
if (data->pdata->checksum)
|
||||
data->checksumming = true;
|
||||
if (data->pdata->no_otp_reload)
|
||||
@@ -924,7 +963,7 @@ static int sht15_probe(struct platform_device *pdev)
|
||||
|
||||
voltage = regulator_get_voltage(data->reg);
|
||||
if (voltage)
|
||||
data->supply_uV = voltage;
|
||||
data->supply_uv = voltage;
|
||||
|
||||
regulator_enable(data->reg);
|
||||
/*
|
||||
@@ -942,17 +981,17 @@ static int sht15_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
/* Try requesting the GPIOs */
|
||||
ret = devm_gpio_request(&pdev->dev, data->pdata->gpio_sck, "SHT15 sck");
|
||||
ret = devm_gpio_request_one(&pdev->dev, data->pdata->gpio_sck,
|
||||
GPIOF_OUT_INIT_LOW, "SHT15 sck");
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "gpio request failed\n");
|
||||
dev_err(&pdev->dev, "clock line GPIO request failed\n");
|
||||
goto err_release_reg;
|
||||
}
|
||||
gpio_direction_output(data->pdata->gpio_sck, 0);
|
||||
|
||||
ret = devm_gpio_request(&pdev->dev, data->pdata->gpio_data,
|
||||
"SHT15 data");
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "gpio request failed\n");
|
||||
dev_err(&pdev->dev, "data line GPIO request failed\n");
|
||||
goto err_release_reg;
|
||||
}
|
||||
|
||||
@@ -966,7 +1005,9 @@ static int sht15_probe(struct platform_device *pdev)
|
||||
goto err_release_reg;
|
||||
}
|
||||
disable_irq_nosync(gpio_to_irq(data->pdata->gpio_data));
|
||||
sht15_connection_reset(data);
|
||||
ret = sht15_connection_reset(data);
|
||||
if (ret)
|
||||
goto err_release_reg;
|
||||
ret = sht15_soft_reset(data);
|
||||
if (ret)
|
||||
goto err_release_reg;
|
||||
|
@@ -132,7 +132,7 @@ static struct platform_device *pdev;
|
||||
*/
|
||||
static inline u8 IN_TO_REG(unsigned long val)
|
||||
{
|
||||
unsigned long nval = SENSORS_LIMIT(val, 0, 4080);
|
||||
unsigned long nval = clamp_val(val, 0, 4080);
|
||||
return (nval + 8) / 16;
|
||||
}
|
||||
#define IN_FROM_REG(val) ((val) * 16)
|
||||
@@ -141,7 +141,7 @@ static inline u8 FAN_TO_REG(long rpm, int div)
|
||||
{
|
||||
if (rpm <= 0)
|
||||
return 255;
|
||||
return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
|
||||
return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
|
||||
}
|
||||
|
||||
static inline int FAN_FROM_REG(u8 val, int div)
|
||||
@@ -159,7 +159,7 @@ static inline int TEMP_FROM_REG(s8 val)
|
||||
}
|
||||
static inline s8 TEMP_TO_REG(int val)
|
||||
{
|
||||
int nval = SENSORS_LIMIT(val, -54120, 157530) ;
|
||||
int nval = clamp_val(val, -54120, 157530) ;
|
||||
return nval < 0 ? (nval - 5212 - 415) / 830 : (nval - 5212 + 415) / 830;
|
||||
}
|
||||
|
||||
|
@@ -326,7 +326,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute
|
||||
/* Preserve fan min */
|
||||
tmp = 192 - (old_div * (192 - data->fan_preload[nr])
|
||||
+ new_div / 2) / new_div;
|
||||
data->fan_preload[nr] = SENSORS_LIMIT(tmp, 0, 191);
|
||||
data->fan_preload[nr] = clamp_val(tmp, 0, 191);
|
||||
smsc47m1_write_value(data, SMSC47M1_REG_FAN_PRELOAD[nr],
|
||||
data->fan_preload[nr]);
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
@@ -77,7 +77,7 @@ static inline unsigned int IN_FROM_REG(u8 reg, int n)
|
||||
|
||||
static inline u8 IN_TO_REG(unsigned long val, int n)
|
||||
{
|
||||
return SENSORS_LIMIT(SCALE(val, 192, nom_mv[n]), 0, 255);
|
||||
return clamp_val(SCALE(val, 192, nom_mv[n]), 0, 255);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -86,7 +86,7 @@ static inline u8 IN_TO_REG(unsigned long val, int n)
|
||||
*/
|
||||
static inline s8 TEMP_TO_REG(int val)
|
||||
{
|
||||
return SENSORS_LIMIT(SCALE(val, 1, 1000), -128000, 127000);
|
||||
return clamp_val(SCALE(val, 1, 1000), -128000, 127000);
|
||||
}
|
||||
|
||||
static inline int TEMP_FROM_REG(s8 val)
|
||||
|
@@ -134,7 +134,7 @@ static ssize_t set_analog_out(struct device *dev,
|
||||
return err;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->analog_out = SENSORS_LIMIT(tmp, 0, 255);
|
||||
data->analog_out = clamp_val(tmp, 0, 255);
|
||||
i2c_smbus_write_byte_data(client, THMC50_REG_ANALOG_OUT,
|
||||
data->analog_out);
|
||||
|
||||
@@ -187,7 +187,7 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
|
||||
return err;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->temp_min[nr] = SENSORS_LIMIT(val / 1000, -128, 127);
|
||||
data->temp_min[nr] = clamp_val(val / 1000, -128, 127);
|
||||
i2c_smbus_write_byte_data(client, THMC50_REG_TEMP_MIN[nr],
|
||||
data->temp_min[nr]);
|
||||
mutex_unlock(&data->update_lock);
|
||||
@@ -216,7 +216,7 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
|
||||
return err;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->temp_max[nr] = SENSORS_LIMIT(val / 1000, -128, 127);
|
||||
data->temp_max[nr] = clamp_val(val / 1000, -128, 127);
|
||||
i2c_smbus_write_byte_data(client, THMC50_REG_TEMP_MAX[nr],
|
||||
data->temp_max[nr]);
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
@@ -115,7 +115,7 @@ static ssize_t tmp102_set_temp(struct device *dev,
|
||||
|
||||
if (kstrtol(buf, 10, &val) < 0)
|
||||
return -EINVAL;
|
||||
val = SENSORS_LIMIT(val, -256000, 255000);
|
||||
val = clamp_val(val, -256000, 255000);
|
||||
|
||||
mutex_lock(&tmp102->lock);
|
||||
tmp102->temp[sda->index] = val;
|
||||
|
@@ -142,10 +142,10 @@ static int tmp401_register_to_temp(u16 reg, u8 config)
|
||||
static u16 tmp401_temp_to_register(long temp, u8 config)
|
||||
{
|
||||
if (config & TMP401_CONFIG_RANGE) {
|
||||
temp = SENSORS_LIMIT(temp, -64000, 191000);
|
||||
temp = clamp_val(temp, -64000, 191000);
|
||||
temp += 64000;
|
||||
} else
|
||||
temp = SENSORS_LIMIT(temp, 0, 127000);
|
||||
temp = clamp_val(temp, 0, 127000);
|
||||
|
||||
return (temp * 160 + 312) / 625;
|
||||
}
|
||||
@@ -163,10 +163,10 @@ static int tmp401_crit_register_to_temp(u8 reg, u8 config)
|
||||
static u8 tmp401_crit_temp_to_register(long temp, u8 config)
|
||||
{
|
||||
if (config & TMP401_CONFIG_RANGE) {
|
||||
temp = SENSORS_LIMIT(temp, -64000, 191000);
|
||||
temp = clamp_val(temp, -64000, 191000);
|
||||
temp += 64000;
|
||||
} else
|
||||
temp = SENSORS_LIMIT(temp, 0, 127000);
|
||||
temp = clamp_val(temp, 0, 127000);
|
||||
|
||||
return (temp + 500) / 1000;
|
||||
}
|
||||
@@ -417,14 +417,14 @@ static ssize_t store_temp_crit_hyst(struct device *dev, struct device_attribute
|
||||
return -EINVAL;
|
||||
|
||||
if (data->config & TMP401_CONFIG_RANGE)
|
||||
val = SENSORS_LIMIT(val, -64000, 191000);
|
||||
val = clamp_val(val, -64000, 191000);
|
||||
else
|
||||
val = SENSORS_LIMIT(val, 0, 127000);
|
||||
val = clamp_val(val, 0, 127000);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
temp = tmp401_crit_register_to_temp(data->temp_crit[index],
|
||||
data->config);
|
||||
val = SENSORS_LIMIT(val, temp - 255000, temp);
|
||||
val = clamp_val(val, temp - 255000, temp);
|
||||
reg = ((temp - val) + 500) / 1000;
|
||||
|
||||
i2c_smbus_write_byte_data(to_i2c_client(dev),
|
||||
|
@@ -135,17 +135,14 @@ static inline u8 IN_TO_REG(long val, int inNum)
|
||||
* for the constants.
|
||||
*/
|
||||
if (inNum <= 1)
|
||||
return (u8)
|
||||
SENSORS_LIMIT((val * 21024 - 1205000) / 250000, 0, 255);
|
||||
return (u8) clamp_val((val * 21024 - 1205000) / 250000, 0, 255);
|
||||
else if (inNum == 2)
|
||||
return (u8)
|
||||
SENSORS_LIMIT((val * 15737 - 1205000) / 250000, 0, 255);
|
||||
return (u8) clamp_val((val * 15737 - 1205000) / 250000, 0, 255);
|
||||
else if (inNum == 3)
|
||||
return (u8)
|
||||
SENSORS_LIMIT((val * 10108 - 1205000) / 250000, 0, 255);
|
||||
return (u8) clamp_val((val * 10108 - 1205000) / 250000, 0, 255);
|
||||
else
|
||||
return (u8)
|
||||
SENSORS_LIMIT((val * 41714 - 12050000) / 2500000, 0, 255);
|
||||
return (u8) clamp_val((val * 41714 - 12050000) / 2500000, 0,
|
||||
255);
|
||||
}
|
||||
|
||||
static inline long IN_FROM_REG(u8 val, int inNum)
|
||||
@@ -175,8 +172,8 @@ static inline u8 FAN_TO_REG(long rpm, int div)
|
||||
{
|
||||
if (rpm == 0)
|
||||
return 0;
|
||||
rpm = SENSORS_LIMIT(rpm, 1, 1000000);
|
||||
return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 255);
|
||||
rpm = clamp_val(rpm, 1, 1000000);
|
||||
return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 255);
|
||||
}
|
||||
|
||||
#define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : (val) == 255 ? 0 : 1350000 / \
|
||||
|
@@ -158,7 +158,7 @@ struct vt1211_data {
|
||||
#define IN_FROM_REG(ix, reg) ((reg) < 3 ? 0 : (ix) == 5 ? \
|
||||
(((reg) - 3) * 15882 + 479) / 958 : \
|
||||
(((reg) - 3) * 10000 + 479) / 958)
|
||||
#define IN_TO_REG(ix, val) (SENSORS_LIMIT((ix) == 5 ? \
|
||||
#define IN_TO_REG(ix, val) (clamp_val((ix) == 5 ? \
|
||||
((val) * 958 + 7941) / 15882 + 3 : \
|
||||
((val) * 958 + 5000) / 10000 + 3, 0, 255))
|
||||
|
||||
@@ -173,7 +173,7 @@ struct vt1211_data {
|
||||
(ix) == 1 ? (reg) < 51 ? 0 : \
|
||||
((reg) - 51) * 1000 : \
|
||||
((253 - (reg)) * 2200 + 105) / 210)
|
||||
#define TEMP_TO_REG(ix, val) SENSORS_LIMIT( \
|
||||
#define TEMP_TO_REG(ix, val) clamp_val( \
|
||||
((ix) == 0 ? ((val) + 500) / 1000 : \
|
||||
(ix) == 1 ? ((val) + 500) / 1000 + 51 : \
|
||||
253 - ((val) * 210 + 1100) / 2200), 0, 255)
|
||||
@@ -183,7 +183,7 @@ struct vt1211_data {
|
||||
#define RPM_FROM_REG(reg, div) (((reg) == 0) || ((reg) == 255) ? 0 : \
|
||||
1310720 / (reg) / DIV_FROM_REG(div))
|
||||
#define RPM_TO_REG(val, div) ((val) == 0 ? 255 : \
|
||||
SENSORS_LIMIT((1310720 / (val) / \
|
||||
clamp_val((1310720 / (val) / \
|
||||
DIV_FROM_REG(div)), 1, 254))
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
@@ -687,7 +687,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
|
||||
data->fan_ctl));
|
||||
break;
|
||||
case SHOW_SET_PWM_FREQ:
|
||||
val = 135000 / SENSORS_LIMIT(val, 135000 >> 7, 135000);
|
||||
val = 135000 / clamp_val(val, 135000 >> 7, 135000);
|
||||
/* calculate tmp = log2(val) */
|
||||
tmp = 0;
|
||||
for (val >>= 1; val > 0; val >>= 1)
|
||||
@@ -845,7 +845,7 @@ static ssize_t set_pwm_auto_point_pwm(struct device *dev,
|
||||
return err;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->pwm_auto_pwm[ix][ap] = SENSORS_LIMIT(val, 0, 255);
|
||||
data->pwm_auto_pwm[ix][ap] = clamp_val(val, 0, 255);
|
||||
vt1211_write8(data, VT1211_REG_PWM_AUTO_PWM(ix, ap),
|
||||
data->pwm_auto_pwm[ix][ap]);
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
@@ -147,7 +147,7 @@ static inline u8 FAN_TO_REG(long rpm, int div)
|
||||
{
|
||||
if (rpm == 0)
|
||||
return 0;
|
||||
return SENSORS_LIMIT(1310720 / (rpm * div), 1, 255);
|
||||
return clamp_val(1310720 / (rpm * div), 1, 255);
|
||||
}
|
||||
|
||||
#define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : 1310720 / ((val) * (div)))
|
||||
@@ -236,7 +236,7 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
|
||||
return err;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->in_min[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255);
|
||||
data->in_min[nr] = clamp_val(((val * 958) / 10000) + 3, 0, 255);
|
||||
vt8231_write_value(data, regvoltmin[nr], data->in_min[nr]);
|
||||
mutex_unlock(&data->update_lock);
|
||||
return count;
|
||||
@@ -256,7 +256,7 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
|
||||
return err;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->in_max[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255);
|
||||
data->in_max[nr] = clamp_val(((val * 958) / 10000) + 3, 0, 255);
|
||||
vt8231_write_value(data, regvoltmax[nr], data->in_max[nr]);
|
||||
mutex_unlock(&data->update_lock);
|
||||
return count;
|
||||
@@ -302,8 +302,8 @@ static ssize_t set_in5_min(struct device *dev, struct device_attribute *attr,
|
||||
return err;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->in_min[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3,
|
||||
0, 255);
|
||||
data->in_min[5] = clamp_val(((val * 958 * 34) / (10000 * 54)) + 3,
|
||||
0, 255);
|
||||
vt8231_write_value(data, regvoltmin[5], data->in_min[5]);
|
||||
mutex_unlock(&data->update_lock);
|
||||
return count;
|
||||
@@ -321,8 +321,8 @@ static ssize_t set_in5_max(struct device *dev, struct device_attribute *attr,
|
||||
return err;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->in_max[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3,
|
||||
0, 255);
|
||||
data->in_max[5] = clamp_val(((val * 958 * 34) / (10000 * 54)) + 3,
|
||||
0, 255);
|
||||
vt8231_write_value(data, regvoltmax[5], data->in_max[5]);
|
||||
mutex_unlock(&data->update_lock);
|
||||
return count;
|
||||
@@ -380,7 +380,7 @@ static ssize_t set_temp0_max(struct device *dev, struct device_attribute *attr,
|
||||
return err;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->temp_max[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255);
|
||||
data->temp_max[0] = clamp_val((val + 500) / 1000, 0, 255);
|
||||
vt8231_write_value(data, regtempmax[0], data->temp_max[0]);
|
||||
mutex_unlock(&data->update_lock);
|
||||
return count;
|
||||
@@ -397,7 +397,7 @@ static ssize_t set_temp0_min(struct device *dev, struct device_attribute *attr,
|
||||
return err;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->temp_min[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255);
|
||||
data->temp_min[0] = clamp_val((val + 500) / 1000, 0, 255);
|
||||
vt8231_write_value(data, regtempmin[0], data->temp_min[0]);
|
||||
mutex_unlock(&data->update_lock);
|
||||
return count;
|
||||
@@ -444,7 +444,7 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
|
||||
return err;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->temp_max[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255);
|
||||
data->temp_max[nr] = clamp_val(TEMP_MAXMIN_TO_REG(val), 0, 255);
|
||||
vt8231_write_value(data, regtempmax[nr], data->temp_max[nr]);
|
||||
mutex_unlock(&data->update_lock);
|
||||
return count;
|
||||
@@ -463,7 +463,7 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
|
||||
return err;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->temp_min[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255);
|
||||
data->temp_min[nr] = clamp_val(TEMP_MAXMIN_TO_REG(val), 0, 255);
|
||||
vt8231_write_value(data, regtempmin[nr], data->temp_min[nr]);
|
||||
mutex_unlock(&data->update_lock);
|
||||
return count;
|
||||
|
@@ -354,8 +354,8 @@ static inline unsigned int step_time_from_reg(u8 reg, u8 mode)
|
||||
|
||||
static inline u8 step_time_to_reg(unsigned int msec, u8 mode)
|
||||
{
|
||||
return SENSORS_LIMIT((mode ? (msec + 50) / 100 :
|
||||
(msec + 200) / 400), 1, 255);
|
||||
return clamp_val((mode ? (msec + 50) / 100 : (msec + 200) / 400),
|
||||
1, 255);
|
||||
}
|
||||
|
||||
static unsigned int fan_from_reg8(u16 reg, unsigned int divreg)
|
||||
@@ -414,8 +414,7 @@ static inline long in_from_reg(u8 reg, u8 nr, const u16 *scale_in)
|
||||
|
||||
static inline u8 in_to_reg(u32 val, u8 nr, const u16 *scale_in)
|
||||
{
|
||||
return SENSORS_LIMIT(DIV_ROUND_CLOSEST(val * 100, scale_in[nr]), 0,
|
||||
255);
|
||||
return clamp_val(DIV_ROUND_CLOSEST(val * 100, scale_in[nr]), 0, 255);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1267,7 +1266,7 @@ store_temp_offset(struct device *dev, struct device_attribute *attr,
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
val = SENSORS_LIMIT(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
|
||||
val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->temp_offset[nr] = val;
|
||||
@@ -1435,7 +1434,7 @@ store_pwm(struct device *dev, struct device_attribute *attr,
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
val = SENSORS_LIMIT(val, 0, 255);
|
||||
val = clamp_val(val, 0, 255);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->pwm[nr] = val;
|
||||
@@ -1514,7 +1513,7 @@ store_target_temp(struct device *dev, struct device_attribute *attr,
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
val = SENSORS_LIMIT(DIV_ROUND_CLOSEST(val, 1000), 0, 127);
|
||||
val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 127);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->target_temp[nr] = val;
|
||||
@@ -1540,7 +1539,7 @@ store_tolerance(struct device *dev, struct device_attribute *attr,
|
||||
return err;
|
||||
|
||||
/* Limit the temp to 0C - 15C */
|
||||
val = SENSORS_LIMIT(DIV_ROUND_CLOSEST(val, 1000), 0, 15);
|
||||
val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 15);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
if (sio_data->kind == nct6775 || sio_data->kind == nct6776) {
|
||||
@@ -1639,7 +1638,7 @@ store_##reg(struct device *dev, struct device_attribute *attr, \
|
||||
err = kstrtoul(buf, 10, &val); \
|
||||
if (err < 0) \
|
||||
return err; \
|
||||
val = SENSORS_LIMIT(val, 1, 255); \
|
||||
val = clamp_val(val, 1, 255); \
|
||||
mutex_lock(&data->update_lock); \
|
||||
data->reg[nr] = val; \
|
||||
w83627ehf_write_value(data, data->REG_##REG[nr], val); \
|
||||
|
@@ -254,16 +254,15 @@ static const u8 BIT_SCFG2[] = { 0x10, 0x20, 0x40 };
|
||||
* these macros are called: arguments may be evaluated more than once.
|
||||
* Fixing this is just not worth it.
|
||||
*/
|
||||
#define IN_TO_REG(val) (SENSORS_LIMIT((((val) + 8)/16),0,255))
|
||||
#define IN_TO_REG(val) (clamp_val((((val) + 8) / 16), 0, 255))
|
||||
#define IN_FROM_REG(val) ((val) * 16)
|
||||
|
||||
static inline u8 FAN_TO_REG(long rpm, int div)
|
||||
{
|
||||
if (rpm == 0)
|
||||
return 255;
|
||||
rpm = SENSORS_LIMIT(rpm, 1, 1000000);
|
||||
return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
|
||||
254);
|
||||
rpm = clamp_val(rpm, 1, 1000000);
|
||||
return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
|
||||
}
|
||||
|
||||
#define TEMP_MIN (-128000)
|
||||
@@ -275,9 +274,9 @@ static inline u8 FAN_TO_REG(long rpm, int div)
|
||||
*/
|
||||
static u8 TEMP_TO_REG(long temp)
|
||||
{
|
||||
int ntemp = SENSORS_LIMIT(temp, TEMP_MIN, TEMP_MAX);
|
||||
ntemp += (ntemp<0 ? -500 : 500);
|
||||
return (u8)(ntemp / 1000);
|
||||
int ntemp = clamp_val(temp, TEMP_MIN, TEMP_MAX);
|
||||
ntemp += (ntemp < 0 ? -500 : 500);
|
||||
return (u8)(ntemp / 1000);
|
||||
}
|
||||
|
||||
static int TEMP_FROM_REG(u8 reg)
|
||||
@@ -287,7 +286,7 @@ static int TEMP_FROM_REG(u8 reg)
|
||||
|
||||
#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div)))
|
||||
|
||||
#define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255))
|
||||
#define PWM_TO_REG(val) (clamp_val((val), 0, 255))
|
||||
|
||||
static inline unsigned long pwm_freq_from_reg_627hf(u8 reg)
|
||||
{
|
||||
@@ -342,7 +341,7 @@ static inline u8 pwm_freq_to_reg(unsigned long val)
|
||||
static inline u8 DIV_TO_REG(long val)
|
||||
{
|
||||
int i;
|
||||
val = SENSORS_LIMIT(val, 1, 128) >> 1;
|
||||
val = clamp_val(val, 1, 128) >> 1;
|
||||
for (i = 0; i < 7; i++) {
|
||||
if (val == 0)
|
||||
break;
|
||||
@@ -614,8 +613,7 @@ static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *a
|
||||
|
||||
/* use VRM9 calculation */
|
||||
data->in_min[0] =
|
||||
SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0,
|
||||
255);
|
||||
clamp_val(((val * 100) - 70000 + 244) / 488, 0, 255);
|
||||
else
|
||||
/* use VRM8 (standard) calculation */
|
||||
data->in_min[0] = IN_TO_REG(val);
|
||||
@@ -644,8 +642,7 @@ static ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *a
|
||||
|
||||
/* use VRM9 calculation */
|
||||
data->in_max[0] =
|
||||
SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0,
|
||||
255);
|
||||
clamp_val(((val * 100) - 70000 + 244) / 488, 0, 255);
|
||||
else
|
||||
/* use VRM8 (standard) calculation */
|
||||
data->in_max[0] = IN_TO_REG(val);
|
||||
|
@@ -159,7 +159,7 @@ static const u8 BIT_SCFG2[] = { 0x10, 0x20, 0x40 };
|
||||
#define W83781D_DEFAULT_BETA 3435
|
||||
|
||||
/* Conversions */
|
||||
#define IN_TO_REG(val) SENSORS_LIMIT(((val) + 8) / 16, 0, 255)
|
||||
#define IN_TO_REG(val) clamp_val(((val) + 8) / 16, 0, 255)
|
||||
#define IN_FROM_REG(val) ((val) * 16)
|
||||
|
||||
static inline u8
|
||||
@@ -167,8 +167,8 @@ FAN_TO_REG(long rpm, int div)
|
||||
{
|
||||
if (rpm == 0)
|
||||
return 255;
|
||||
rpm = SENSORS_LIMIT(rpm, 1, 1000000);
|
||||
return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
|
||||
rpm = clamp_val(rpm, 1, 1000000);
|
||||
return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
|
||||
}
|
||||
|
||||
static inline long
|
||||
@@ -181,7 +181,7 @@ FAN_FROM_REG(u8 val, int div)
|
||||
return 1350000 / (val * div);
|
||||
}
|
||||
|
||||
#define TEMP_TO_REG(val) SENSORS_LIMIT((val) / 1000, -127, 128)
|
||||
#define TEMP_TO_REG(val) clamp_val((val) / 1000, -127, 128)
|
||||
#define TEMP_FROM_REG(val) ((val) * 1000)
|
||||
|
||||
#define BEEP_MASK_FROM_REG(val, type) ((type) == as99127f ? \
|
||||
@@ -195,9 +195,8 @@ static inline u8
|
||||
DIV_TO_REG(long val, enum chips type)
|
||||
{
|
||||
int i;
|
||||
val = SENSORS_LIMIT(val, 1,
|
||||
((type == w83781d
|
||||
|| type == as99127f) ? 8 : 128)) >> 1;
|
||||
val = clamp_val(val, 1,
|
||||
((type == w83781d || type == as99127f) ? 8 : 128)) >> 1;
|
||||
for (i = 0; i < 7; i++) {
|
||||
if (val == 0)
|
||||
break;
|
||||
@@ -443,7 +442,7 @@ store_vrm_reg(struct device *dev, struct device_attribute *attr,
|
||||
err = kstrtoul(buf, 10, &val);
|
||||
if (err)
|
||||
return err;
|
||||
data->vrm = SENSORS_LIMIT(val, 0, 255);
|
||||
data->vrm = clamp_val(val, 0, 255);
|
||||
|
||||
return count;
|
||||
}
|
||||
@@ -730,7 +729,7 @@ store_pwm(struct device *dev, struct device_attribute *da, const char *buf,
|
||||
return err;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->pwm[nr] = SENSORS_LIMIT(val, 0, 255);
|
||||
data->pwm[nr] = clamp_val(val, 0, 255);
|
||||
w83781d_write_value(data, W83781D_REG_PWM[nr], data->pwm[nr]);
|
||||
mutex_unlock(&data->update_lock);
|
||||
return count;
|
||||
|
@@ -220,15 +220,15 @@ static inline int w83791d_write(struct i2c_client *client, u8 reg, u8 value)
|
||||
* in mV as would be measured on the chip input pin, need to just
|
||||
* multiply/divide by 16 to translate from/to register values.
|
||||
*/
|
||||
#define IN_TO_REG(val) (SENSORS_LIMIT((((val) + 8) / 16), 0, 255))
|
||||
#define IN_TO_REG(val) (clamp_val((((val) + 8) / 16), 0, 255))
|
||||
#define IN_FROM_REG(val) ((val) * 16)
|
||||
|
||||
static u8 fan_to_reg(long rpm, int div)
|
||||
{
|
||||
if (rpm == 0)
|
||||
return 255;
|
||||
rpm = SENSORS_LIMIT(rpm, 1, 1000000);
|
||||
return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
|
||||
rpm = clamp_val(rpm, 1, 1000000);
|
||||
return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
|
||||
}
|
||||
|
||||
#define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : \
|
||||
@@ -273,7 +273,7 @@ static u8 div_to_reg(int nr, long val)
|
||||
int i;
|
||||
|
||||
/* fan divisors max out at 128 */
|
||||
val = SENSORS_LIMIT(val, 1, 128) >> 1;
|
||||
val = clamp_val(val, 1, 128) >> 1;
|
||||
for (i = 0; i < 7; i++) {
|
||||
if (val == 0)
|
||||
break;
|
||||
@@ -747,7 +747,7 @@ static ssize_t store_pwm(struct device *dev, struct device_attribute *attr,
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->pwm[nr] = SENSORS_LIMIT(val, 0, 255);
|
||||
data->pwm[nr] = clamp_val(val, 0, 255);
|
||||
w83791d_write(client, W83791D_REG_PWM[nr], data->pwm[nr]);
|
||||
mutex_unlock(&data->update_lock);
|
||||
return count;
|
||||
|
@@ -235,8 +235,8 @@ FAN_TO_REG(long rpm, int div)
|
||||
{
|
||||
if (rpm == 0)
|
||||
return 255;
|
||||
rpm = SENSORS_LIMIT(rpm, 1, 1000000);
|
||||
return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
|
||||
rpm = clamp_val(rpm, 1, 1000000);
|
||||
return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
|
||||
}
|
||||
|
||||
#define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : \
|
||||
@@ -244,16 +244,15 @@ FAN_TO_REG(long rpm, int div)
|
||||
1350000 / ((val) * (div))))
|
||||
|
||||
/* for temp1 */
|
||||
#define TEMP1_TO_REG(val) (SENSORS_LIMIT(((val) < 0 ? (val)+0x100*1000 \
|
||||
: (val)) / 1000, 0, 0xff))
|
||||
#define TEMP1_TO_REG(val) (clamp_val(((val) < 0 ? (val) + 0x100 * 1000 \
|
||||
: (val)) / 1000, 0, 0xff))
|
||||
#define TEMP1_FROM_REG(val) (((val) & 0x80 ? (val)-0x100 : (val)) * 1000)
|
||||
/* for temp2 and temp3, because they need additional resolution */
|
||||
#define TEMP_ADD_FROM_REG(val1, val2) \
|
||||
((((val1) & 0x80 ? (val1)-0x100 \
|
||||
: (val1)) * 1000) + ((val2 & 0x80) ? 500 : 0))
|
||||
#define TEMP_ADD_TO_REG_HIGH(val) \
|
||||
(SENSORS_LIMIT(((val) < 0 ? (val)+0x100*1000 \
|
||||
: (val)) / 1000, 0, 0xff))
|
||||
(clamp_val(((val) < 0 ? (val) + 0x100 * 1000 : (val)) / 1000, 0, 0xff))
|
||||
#define TEMP_ADD_TO_REG_LOW(val) ((val%1000) ? 0x80 : 0x00)
|
||||
|
||||
#define DIV_FROM_REG(val) (1 << (val))
|
||||
@@ -262,7 +261,7 @@ static inline u8
|
||||
DIV_TO_REG(long val)
|
||||
{
|
||||
int i;
|
||||
val = SENSORS_LIMIT(val, 1, 128) >> 1;
|
||||
val = clamp_val(val, 1, 128) >> 1;
|
||||
for (i = 0; i < 7; i++) {
|
||||
if (val == 0)
|
||||
break;
|
||||
@@ -397,7 +396,7 @@ static ssize_t store_in_##reg(struct device *dev, \
|
||||
if (err) \
|
||||
return err; \
|
||||
mutex_lock(&data->update_lock); \
|
||||
data->in_##reg[nr] = SENSORS_LIMIT(IN_TO_REG(nr, val) / 4, 0, 255); \
|
||||
data->in_##reg[nr] = clamp_val(IN_TO_REG(nr, val) / 4, 0, 255); \
|
||||
w83792d_write_value(client, W83792D_REG_IN_##REG[nr], \
|
||||
data->in_##reg[nr]); \
|
||||
mutex_unlock(&data->update_lock); \
|
||||
@@ -645,7 +644,7 @@ store_pwm(struct device *dev, struct device_attribute *attr,
|
||||
err = kstrtoul(buf, 10, &val);
|
||||
if (err)
|
||||
return err;
|
||||
val = SENSORS_LIMIT(val, 0, 255) >> 4;
|
||||
val = clamp_val(val, 0, 255) >> 4;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
val |= w83792d_read_value(client, W83792D_REG_PWM[nr]) & 0xf0;
|
||||
@@ -799,7 +798,7 @@ store_thermal_cruise(struct device *dev, struct device_attribute *attr,
|
||||
mutex_lock(&data->update_lock);
|
||||
target_mask = w83792d_read_value(client,
|
||||
W83792D_REG_THERMAL[nr]) & 0x80;
|
||||
data->thermal_cruise[nr] = SENSORS_LIMIT(target_tmp, 0, 255);
|
||||
data->thermal_cruise[nr] = clamp_val(target_tmp, 0, 255);
|
||||
w83792d_write_value(client, W83792D_REG_THERMAL[nr],
|
||||
(data->thermal_cruise[nr]) | target_mask);
|
||||
mutex_unlock(&data->update_lock);
|
||||
@@ -837,7 +836,7 @@ store_tolerance(struct device *dev, struct device_attribute *attr,
|
||||
mutex_lock(&data->update_lock);
|
||||
tol_mask = w83792d_read_value(client,
|
||||
W83792D_REG_TOLERANCE[nr]) & ((nr == 1) ? 0x0f : 0xf0);
|
||||
tol_tmp = SENSORS_LIMIT(val, 0, 15);
|
||||
tol_tmp = clamp_val(val, 0, 15);
|
||||
tol_tmp &= 0x0f;
|
||||
data->tolerance[nr] = tol_tmp;
|
||||
if (nr == 1)
|
||||
@@ -881,7 +880,7 @@ store_sf2_point(struct device *dev, struct device_attribute *attr,
|
||||
return err;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->sf2_points[index][nr] = SENSORS_LIMIT(val, 0, 127);
|
||||
data->sf2_points[index][nr] = clamp_val(val, 0, 127);
|
||||
mask_tmp = w83792d_read_value(client,
|
||||
W83792D_REG_POINTS[index][nr]) & 0x80;
|
||||
w83792d_write_value(client, W83792D_REG_POINTS[index][nr],
|
||||
@@ -923,7 +922,7 @@ store_sf2_level(struct device *dev, struct device_attribute *attr,
|
||||
return err;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->sf2_levels[index][nr] = SENSORS_LIMIT((val * 15) / 100, 0, 15);
|
||||
data->sf2_levels[index][nr] = clamp_val((val * 15) / 100, 0, 15);
|
||||
mask_tmp = w83792d_read_value(client, W83792D_REG_LEVELS[index][nr])
|
||||
& ((nr == 3) ? 0xf0 : 0x0f);
|
||||
if (nr == 3)
|
||||
|
@@ -191,7 +191,7 @@ static inline u16 FAN_TO_REG(long rpm)
|
||||
{
|
||||
if (rpm <= 0)
|
||||
return 0x0fff;
|
||||
return SENSORS_LIMIT((1350000 + (rpm >> 1)) / rpm, 1, 0xffe);
|
||||
return clamp_val((1350000 + (rpm >> 1)) / rpm, 1, 0xffe);
|
||||
}
|
||||
|
||||
static inline unsigned long TIME_FROM_REG(u8 reg)
|
||||
@@ -201,7 +201,7 @@ static inline unsigned long TIME_FROM_REG(u8 reg)
|
||||
|
||||
static inline u8 TIME_TO_REG(unsigned long val)
|
||||
{
|
||||
return SENSORS_LIMIT((val + 50) / 100, 0, 0xff);
|
||||
return clamp_val((val + 50) / 100, 0, 0xff);
|
||||
}
|
||||
|
||||
static inline long TEMP_FROM_REG(s8 reg)
|
||||
@@ -211,7 +211,7 @@ static inline long TEMP_FROM_REG(s8 reg)
|
||||
|
||||
static inline s8 TEMP_TO_REG(long val, s8 min, s8 max)
|
||||
{
|
||||
return SENSORS_LIMIT((val + (val < 0 ? -500 : 500)) / 1000, min, max);
|
||||
return clamp_val((val + (val < 0 ? -500 : 500)) / 1000, min, max);
|
||||
}
|
||||
|
||||
struct w83793_data {
|
||||
@@ -558,7 +558,7 @@ store_pwm(struct device *dev, struct device_attribute *attr,
|
||||
w83793_write_value(client, W83793_REG_PWM_STOP_TIME(index),
|
||||
val);
|
||||
} else {
|
||||
val = SENSORS_LIMIT(val, 0, 0xff) >> 2;
|
||||
val = clamp_val(val, 0, 0xff) >> 2;
|
||||
data->pwm[index][nr] =
|
||||
w83793_read_value(client, W83793_REG_PWM(index, nr)) & 0xc0;
|
||||
data->pwm[index][nr] |= val;
|
||||
@@ -739,7 +739,7 @@ store_sf_setup(struct device *dev, struct device_attribute *attr,
|
||||
if (nr == SETUP_PWM_DEFAULT) {
|
||||
data->pwm_default =
|
||||
w83793_read_value(client, W83793_REG_PWM_DEFAULT) & 0xc0;
|
||||
data->pwm_default |= SENSORS_LIMIT(val, 0, 0xff) >> 2;
|
||||
data->pwm_default |= clamp_val(val, 0, 0xff) >> 2;
|
||||
w83793_write_value(client, W83793_REG_PWM_DEFAULT,
|
||||
data->pwm_default);
|
||||
} else if (nr == SETUP_PWM_UPTIME) {
|
||||
@@ -838,7 +838,7 @@ store_sf_ctrl(struct device *dev, struct device_attribute *attr,
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
if (nr == TEMP_FAN_MAP) {
|
||||
val = SENSORS_LIMIT(val, 0, 255);
|
||||
val = clamp_val(val, 0, 255);
|
||||
w83793_write_value(client, W83793_REG_TEMP_FAN_MAP(index), val);
|
||||
data->temp_fan_map[index] = val;
|
||||
} else if (nr == TEMP_PWM_ENABLE) {
|
||||
@@ -907,7 +907,7 @@ store_sf2_pwm(struct device *dev, struct device_attribute *attr,
|
||||
err = kstrtoul(buf, 10, &val);
|
||||
if (err)
|
||||
return err;
|
||||
val = SENSORS_LIMIT(val, 0, 0xff) >> 2;
|
||||
val = clamp_val(val, 0, 0xff) >> 2;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->sf2_pwm[index][nr] =
|
||||
@@ -1003,9 +1003,9 @@ store_in(struct device *dev, struct device_attribute *attr,
|
||||
/* fix the limit values of 5VDD and 5VSB to ALARM mechanism */
|
||||
if (nr == 1 || nr == 2)
|
||||
val -= scale_in_add[index] / scale_in[index];
|
||||
val = SENSORS_LIMIT(val, 0, 255);
|
||||
val = clamp_val(val, 0, 255);
|
||||
} else {
|
||||
val = SENSORS_LIMIT(val, 0, 0x3FF);
|
||||
val = clamp_val(val, 0, 0x3FF);
|
||||
data->in_low_bits[nr] =
|
||||
w83793_read_value(client, W83793_REG_IN_LOW_BITS[nr]);
|
||||
data->in_low_bits[nr] &= ~(0x03 << (2 * index));
|
||||
|
@@ -262,7 +262,7 @@ static inline u16 fan_to_reg(long rpm)
|
||||
{
|
||||
if (rpm <= 0)
|
||||
return 0x0fff;
|
||||
return SENSORS_LIMIT((1350000 + (rpm >> 1)) / rpm, 1, 0xffe);
|
||||
return clamp_val((1350000 + (rpm >> 1)) / rpm, 1, 0xffe);
|
||||
}
|
||||
|
||||
static inline unsigned long time_from_reg(u8 reg)
|
||||
@@ -272,7 +272,7 @@ static inline unsigned long time_from_reg(u8 reg)
|
||||
|
||||
static inline u8 time_to_reg(unsigned long val)
|
||||
{
|
||||
return SENSORS_LIMIT((val + 50) / 100, 0, 0xff);
|
||||
return clamp_val((val + 50) / 100, 0, 0xff);
|
||||
}
|
||||
|
||||
static inline long temp_from_reg(s8 reg)
|
||||
@@ -282,7 +282,7 @@ static inline long temp_from_reg(s8 reg)
|
||||
|
||||
static inline s8 temp_to_reg(long val, s8 min, s8 max)
|
||||
{
|
||||
return SENSORS_LIMIT(val / 1000, min, max);
|
||||
return clamp_val(val / 1000, min, max);
|
||||
}
|
||||
|
||||
static const u16 pwm_freq_cksel0[16] = {
|
||||
@@ -319,7 +319,7 @@ static u8 pwm_freq_to_reg(unsigned long val, u16 clkin)
|
||||
|
||||
/* Best fit for cksel = 1 */
|
||||
base_clock = clkin * 1000 / ((clkin == 48000) ? 384 : 256);
|
||||
reg1 = SENSORS_LIMIT(DIV_ROUND_CLOSEST(base_clock, val), 1, 128);
|
||||
reg1 = clamp_val(DIV_ROUND_CLOSEST(base_clock, val), 1, 128);
|
||||
best1 = base_clock / reg1;
|
||||
reg1 = 0x80 | (reg1 - 1);
|
||||
|
||||
@@ -889,7 +889,7 @@ store_pwm(struct device *dev, struct device_attribute *attr,
|
||||
val = pwm_freq_to_reg(val, data->clkin);
|
||||
break;
|
||||
default:
|
||||
val = SENSORS_LIMIT(val, 0, 0xff);
|
||||
val = clamp_val(val, 0, 0xff);
|
||||
break;
|
||||
}
|
||||
w83795_write(client, W83795_REG_PWM(index, nr), val);
|
||||
@@ -1126,7 +1126,7 @@ store_temp_pwm_enable(struct device *dev, struct device_attribute *attr,
|
||||
break;
|
||||
case TEMP_PWM_FAN_MAP:
|
||||
mutex_lock(&data->update_lock);
|
||||
tmp = SENSORS_LIMIT(tmp, 0, 0xff);
|
||||
tmp = clamp_val(tmp, 0, 0xff);
|
||||
w83795_write(client, W83795_REG_TFMR(index), tmp);
|
||||
data->pwm_tfmr[index] = tmp;
|
||||
mutex_unlock(&data->update_lock);
|
||||
@@ -1177,13 +1177,13 @@ store_fanin(struct device *dev, struct device_attribute *attr,
|
||||
mutex_lock(&data->update_lock);
|
||||
switch (nr) {
|
||||
case FANIN_TARGET:
|
||||
val = fan_to_reg(SENSORS_LIMIT(val, 0, 0xfff));
|
||||
val = fan_to_reg(clamp_val(val, 0, 0xfff));
|
||||
w83795_write(client, W83795_REG_FTSH(index), val >> 4);
|
||||
w83795_write(client, W83795_REG_FTSL(index), (val << 4) & 0xf0);
|
||||
data->target_speed[index] = val;
|
||||
break;
|
||||
case FANIN_TOL:
|
||||
val = SENSORS_LIMIT(val, 0, 0x3f);
|
||||
val = clamp_val(val, 0, 0x3f);
|
||||
w83795_write(client, W83795_REG_TFTS, val);
|
||||
data->tol_speed = val;
|
||||
break;
|
||||
@@ -1227,22 +1227,22 @@ store_temp_pwm(struct device *dev, struct device_attribute *attr,
|
||||
mutex_lock(&data->update_lock);
|
||||
switch (nr) {
|
||||
case TEMP_PWM_TTTI:
|
||||
val = SENSORS_LIMIT(val, 0, 0x7f);
|
||||
val = clamp_val(val, 0, 0x7f);
|
||||
w83795_write(client, W83795_REG_TTTI(index), val);
|
||||
break;
|
||||
case TEMP_PWM_CTFS:
|
||||
val = SENSORS_LIMIT(val, 0, 0x7f);
|
||||
val = clamp_val(val, 0, 0x7f);
|
||||
w83795_write(client, W83795_REG_CTFS(index), val);
|
||||
break;
|
||||
case TEMP_PWM_HCT:
|
||||
val = SENSORS_LIMIT(val, 0, 0x0f);
|
||||
val = clamp_val(val, 0, 0x0f);
|
||||
tmp = w83795_read(client, W83795_REG_HT(index));
|
||||
tmp &= 0x0f;
|
||||
tmp |= (val << 4) & 0xf0;
|
||||
w83795_write(client, W83795_REG_HT(index), tmp);
|
||||
break;
|
||||
case TEMP_PWM_HOT:
|
||||
val = SENSORS_LIMIT(val, 0, 0x0f);
|
||||
val = clamp_val(val, 0, 0x0f);
|
||||
tmp = w83795_read(client, W83795_REG_HT(index));
|
||||
tmp &= 0xf0;
|
||||
tmp |= val & 0x0f;
|
||||
@@ -1541,7 +1541,7 @@ store_in(struct device *dev, struct device_attribute *attr,
|
||||
if ((index >= 17) &&
|
||||
!((data->has_gain >> (index - 17)) & 1))
|
||||
val /= 8;
|
||||
val = SENSORS_LIMIT(val, 0, 0x3FF);
|
||||
val = clamp_val(val, 0, 0x3FF);
|
||||
mutex_lock(&data->update_lock);
|
||||
|
||||
lsb_idx = IN_LSB_SHIFT_IDX[index][IN_LSB_IDX];
|
||||
@@ -1596,7 +1596,7 @@ store_sf_setup(struct device *dev, struct device_attribute *attr,
|
||||
|
||||
switch (nr) {
|
||||
case SETUP_PWM_DEFAULT:
|
||||
val = SENSORS_LIMIT(val, 0, 0xff);
|
||||
val = clamp_val(val, 0, 0xff);
|
||||
break;
|
||||
case SETUP_PWM_UPTIME:
|
||||
case SETUP_PWM_DOWNTIME:
|
||||
|
@@ -86,8 +86,8 @@ FAN_TO_REG(long rpm, int div)
|
||||
{
|
||||
if (rpm == 0)
|
||||
return 255;
|
||||
rpm = SENSORS_LIMIT(rpm, 1, 1000000);
|
||||
return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
|
||||
rpm = clamp_val(rpm, 1, 1000000);
|
||||
return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
|
||||
}
|
||||
|
||||
#define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : \
|
||||
@@ -95,9 +95,8 @@ FAN_TO_REG(long rpm, int div)
|
||||
1350000 / ((val) * (div))))
|
||||
|
||||
/* for temp */
|
||||
#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val) < 0 ? \
|
||||
(val) + 0x100 * 1000 \
|
||||
: (val)) / 1000, 0, 0xff))
|
||||
#define TEMP_TO_REG(val) (clamp_val(((val) < 0 ? (val) + 0x100 * 1000 \
|
||||
: (val)) / 1000, 0, 0xff))
|
||||
#define TEMP_FROM_REG(val) (((val) & 0x80 ? \
|
||||
(val) - 0x100 : (val)) * 1000)
|
||||
|
||||
@@ -106,7 +105,7 @@ FAN_TO_REG(long rpm, int div)
|
||||
* in mV as would be measured on the chip input pin, need to just
|
||||
* multiply/divide by 8 to translate from/to register values.
|
||||
*/
|
||||
#define IN_TO_REG(val) (SENSORS_LIMIT((((val) + 4) / 8), 0, 255))
|
||||
#define IN_TO_REG(val) (clamp_val((((val) + 4) / 8), 0, 255))
|
||||
#define IN_FROM_REG(val) ((val) * 8)
|
||||
|
||||
#define DIV_FROM_REG(val) (1 << (val))
|
||||
@@ -115,7 +114,7 @@ static inline u8
|
||||
DIV_TO_REG(long val)
|
||||
{
|
||||
int i;
|
||||
val = SENSORS_LIMIT(val, 1, 128) >> 1;
|
||||
val = clamp_val(val, 1, 128) >> 1;
|
||||
for (i = 0; i < 7; i++) {
|
||||
if (val == 0)
|
||||
break;
|
||||
@@ -481,7 +480,7 @@ store_pwm(struct device *dev, struct device_attribute *attr,
|
||||
err = kstrtoul(buf, 10, &val);
|
||||
if (err)
|
||||
return err;
|
||||
val = SENSORS_LIMIT(val, 0, 255);
|
||||
val = clamp_val(val, 0, 255);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->pwm[nr] = val;
|
||||
@@ -564,7 +563,7 @@ store_tolerance(struct device *dev, struct device_attribute *attr,
|
||||
mutex_lock(&data->update_lock);
|
||||
tol_mask = w83l786ng_read_value(client,
|
||||
W83L786NG_REG_TOLERANCE) & ((nr == 1) ? 0x0f : 0xf0);
|
||||
tol_tmp = SENSORS_LIMIT(val, 0, 15);
|
||||
tol_tmp = clamp_val(val, 0, 15);
|
||||
tol_tmp &= 0x0f;
|
||||
data->tolerance[nr] = tol_tmp;
|
||||
if (nr == 1)
|
||||
|
@@ -1007,7 +1007,7 @@ static int eeepc_get_fan_pwm(void)
|
||||
|
||||
static void eeepc_set_fan_pwm(int value)
|
||||
{
|
||||
value = SENSORS_LIMIT(value, 0, 255);
|
||||
value = clamp_val(value, 0, 255);
|
||||
value = value * 100 / 255;
|
||||
ec_write(EEEPC_EC_FAN_PWM, value);
|
||||
}
|
||||
|
@@ -20,16 +20,4 @@ struct device *hwmon_device_register(struct device *dev);
|
||||
|
||||
void hwmon_device_unregister(struct device *dev);
|
||||
|
||||
/* Scale user input to sensible values */
|
||||
static inline int SENSORS_LIMIT(long value, long low, long high)
|
||||
{
|
||||
if (value < low)
|
||||
return low;
|
||||
else if (value > high)
|
||||
return high;
|
||||
else
|
||||
return value;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
36
include/linux/platform_data/max6697.h
Normal file
36
include/linux/platform_data/max6697.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* max6697.h
|
||||
* Copyright (c) 2012 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 version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef MAX6697_H
|
||||
#define MAX6697_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/*
|
||||
* For all bit masks:
|
||||
* bit 0: local temperature
|
||||
* bit 1..7: remote temperatures
|
||||
*/
|
||||
struct max6697_platform_data {
|
||||
bool smbus_timeout_disable; /* set to disable SMBus timeouts */
|
||||
bool extended_range_enable; /* set to enable extended temp range */
|
||||
bool beta_compensation; /* set to enable beta compensation */
|
||||
u8 alert_mask; /* set bit to 1 to disable alert */
|
||||
u8 over_temperature_mask; /* set bit to 1 to disable */
|
||||
u8 resistance_cancellation; /* set bit to 0 to disable
|
||||
* bit mask for MAX6581,
|
||||
* boolean for other chips
|
||||
*/
|
||||
u8 ideality_mask; /* set bit to 0 to disable */
|
||||
u8 ideality_value; /* transistor ideality as per
|
||||
* MAX6581 datasheet
|
||||
*/
|
||||
};
|
||||
|
||||
#endif /* MAX6697_H */
|
Reference in New Issue
Block a user