You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/hwmon-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/hwmon-2.6: (39 commits) hwmon: Remove Yuan Mu's address hwmon: Fix unchecked return status, SMSC chips hwmon: Fix unchecked return status, batch 6 w83792d: Fix unchecked return status w83l785ts: Fix unchecked return status w83781d: Fix unchecked return status vt8231: Fix unchecked return status Fix unchecked return status, batch 5 hwmon: Fix unchecked return status, batch 4 hwmon: Fix unchecked return status, batch 3 hwmon: Fix unchecked return status, batch 2 w83627ehf: Fix unchecked return status pc87360: Check for error on sysfs files creation pc87360: Delete sysfs files on device deletion pc87360: Move some code around hwmon: Fix unchecked return status, batch 1 vt1211: Document module parameters vt1211: Add documentation hwmon: New driver for the VIA VT1211 w83791d: Documentation update ...
This commit is contained in:
+47
-14
@@ -13,12 +13,25 @@ Supported chips:
|
||||
from Super I/O config space (8 I/O ports)
|
||||
Datasheet: Publicly available at the ITE website
|
||||
http://www.ite.com.tw/
|
||||
* IT8716F
|
||||
Prefix: 'it8716'
|
||||
Addresses scanned: from Super I/O config space (8 I/O ports)
|
||||
Datasheet: Publicly available at the ITE website
|
||||
http://www.ite.com.tw/product_info/file/pc/IT8716F_V0.3.ZIP
|
||||
* IT8718F
|
||||
Prefix: 'it8718'
|
||||
Addresses scanned: from Super I/O config space (8 I/O ports)
|
||||
Datasheet: Publicly available at the ITE website
|
||||
http://www.ite.com.tw/product_info/file/pc/IT8718F_V0.2.zip
|
||||
http://www.ite.com.tw/product_info/file/pc/IT8718F_V0%203_(for%20C%20version).zip
|
||||
* SiS950 [clone of IT8705F]
|
||||
Prefix: 'it87'
|
||||
Addresses scanned: from Super I/O config space (8 I/O ports)
|
||||
Datasheet: No longer be available
|
||||
|
||||
Author: Christophe Gauthron <chrisg@0-in.com>
|
||||
Authors:
|
||||
Christophe Gauthron <chrisg@0-in.com>
|
||||
Jean Delvare <khali@linux-fr.org>
|
||||
|
||||
|
||||
Module Parameters
|
||||
@@ -43,26 +56,46 @@ Module Parameters
|
||||
Description
|
||||
-----------
|
||||
|
||||
This driver implements support for the IT8705F, IT8712F and SiS950 chips.
|
||||
|
||||
This driver also supports IT8712F, which adds SMBus access, and a VID
|
||||
input, used to report the Vcore voltage of the Pentium processor.
|
||||
The IT8712F additionally features VID inputs.
|
||||
This driver implements support for the IT8705F, IT8712F, IT8716F,
|
||||
IT8718F and SiS950 chips.
|
||||
|
||||
These chips are 'Super I/O chips', supporting floppy disks, infrared ports,
|
||||
joysticks and other miscellaneous stuff. For hardware monitoring, they
|
||||
include an 'environment controller' with 3 temperature sensors, 3 fan
|
||||
rotation speed sensors, 8 voltage sensors, and associated alarms.
|
||||
|
||||
The IT8712F and IT8716F additionally feature VID inputs, used to report
|
||||
the Vcore voltage of the processor. The early IT8712F have 5 VID pins,
|
||||
the IT8716F and late IT8712F have 6. They are shared with other functions
|
||||
though, so the functionality may not be available on a given system.
|
||||
The driver dumbly assume it is there.
|
||||
|
||||
The IT8718F also features VID inputs (up to 8 pins) but the value is
|
||||
stored in the Super-I/O configuration space. Due to technical limitations,
|
||||
this value can currently only be read once at initialization time, so
|
||||
the driver won't notice and report changes in the VID value. The two
|
||||
upper VID bits share their pins with voltage inputs (in5 and in6) so you
|
||||
can't have both on a given board.
|
||||
|
||||
The IT8716F, IT8718F and later IT8712F revisions have support for
|
||||
2 additional fans. They are not yet supported by the driver.
|
||||
|
||||
The IT8716F and IT8718F, and late IT8712F and IT8705F also have optional
|
||||
16-bit tachometer counters for fans 1 to 3. This is better (no more fan
|
||||
clock divider mess) but not compatible with the older chips and
|
||||
revisions. For now, the driver only uses the 16-bit mode on the
|
||||
IT8716F and IT8718F.
|
||||
|
||||
Temperatures are measured in degrees Celsius. An alarm is triggered once
|
||||
when the Overtemperature Shutdown limit is crossed.
|
||||
|
||||
Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
|
||||
triggered if the rotation speed has dropped below a programmable limit. Fan
|
||||
readings can be divided by a programmable divider (1, 2, 4 or 8) to give the
|
||||
readings more range or accuracy. Not all RPM values can accurately be
|
||||
represented, so some rounding is done. With a divider of 2, the lowest
|
||||
representable value is around 2600 RPM.
|
||||
triggered if the rotation speed has dropped below a programmable limit. When
|
||||
16-bit tachometer counters aren't used, fan readings can be divided by
|
||||
a programmable divider (1, 2, 4 or 8) to give the readings more range or
|
||||
accuracy. With a divider of 2, the lowest representable value is around
|
||||
2600 RPM. Not all RPM values can accurately be represented, so some rounding
|
||||
is done.
|
||||
|
||||
Voltage sensors (also known as IN sensors) report their values in volts. An
|
||||
alarm is triggered if the voltage has crossed a programmable minimum or
|
||||
@@ -71,9 +104,9 @@ zero'; this is important for negative voltage measurements. All voltage
|
||||
inputs can measure voltages between 0 and 4.08 volts, with a resolution of
|
||||
0.016 volt. The battery voltage in8 does not have limit registers.
|
||||
|
||||
The VID lines (IT8712F only) encode the core voltage value: the voltage
|
||||
level your processor should work with. This is hardcoded by the mainboard
|
||||
and/or processor itself. It is a value in volts.
|
||||
The VID lines (IT8712F/IT8716F/IT8718F) encode the core voltage value:
|
||||
the voltage level your processor should work with. This is hardcoded by
|
||||
the mainboard and/or processor itself. It is a value in volts.
|
||||
|
||||
If an alarm triggers, it will remain triggered until the hardware register
|
||||
is read at least once. This means that the cause for the alarm may already
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
Kernel driver k8temp
|
||||
====================
|
||||
|
||||
Supported chips:
|
||||
* AMD K8 CPU
|
||||
Prefix: 'k8temp'
|
||||
Addresses scanned: PCI space
|
||||
Datasheet: http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/32559.pdf
|
||||
|
||||
Author: Rudolf Marek
|
||||
Contact: Rudolf Marek <r.marek@sh.cvut.cz>
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
This driver permits reading temperature sensor(s) embedded inside AMD K8 CPUs.
|
||||
Official documentation says that it works from revision F of K8 core, but
|
||||
in fact it seems to be implemented for all revisions of K8 except the first
|
||||
two revisions (SH-B0 and SH-B3).
|
||||
|
||||
There can be up to four temperature sensors inside single CPU. The driver
|
||||
will auto-detect the sensors and will display only temperatures from
|
||||
implemented sensors.
|
||||
|
||||
Mapping of /sys files is as follows:
|
||||
|
||||
temp1_input - temperature of Core 0 and "place" 0
|
||||
temp2_input - temperature of Core 0 and "place" 1
|
||||
temp3_input - temperature of Core 1 and "place" 0
|
||||
temp4_input - temperature of Core 1 and "place" 1
|
||||
|
||||
Temperatures are measured in degrees Celsius and measurement resolution is
|
||||
1 degree C. It is expected that future CPU will have better resolution. The
|
||||
temperature is updated once a second. Valid temperatures are from -49 to
|
||||
206 degrees C.
|
||||
|
||||
Temperature known as TCaseMax was specified for processors up to revision E.
|
||||
This temperature is defined as temperature between heat-spreader and CPU
|
||||
case, so the internal CPU temperature supplied by this driver can be higher.
|
||||
There is no easy way how to measure the temperature which will correlate
|
||||
with TCaseMax temperature.
|
||||
|
||||
For newer revisions of CPU (rev F, socket AM2) there is a mathematically
|
||||
computed temperature called TControl, which must be lower than TControlMax.
|
||||
|
||||
The relationship is following:
|
||||
|
||||
temp1_input - TjOffset*2 < TControlMax,
|
||||
|
||||
TjOffset is not yet exported by the driver, TControlMax is usually
|
||||
70 degrees C. The rule of the thumb -> CPU temperature should not cross
|
||||
60 degrees C too much.
|
||||
@@ -0,0 +1,206 @@
|
||||
Kernel driver vt1211
|
||||
====================
|
||||
|
||||
Supported chips:
|
||||
* VIA VT1211
|
||||
Prefix: 'vt1211'
|
||||
Addresses scanned: none, address read from Super-I/O config space
|
||||
Datasheet: Provided by VIA upon request and under NDA
|
||||
|
||||
Authors: Juerg Haefliger <juergh@gmail.com>
|
||||
|
||||
This driver is based on the driver for kernel 2.4 by Mark D. Studebaker and
|
||||
its port to kernel 2.6 by Lars Ekman.
|
||||
|
||||
Thanks to Joseph Chan and Fiona Gatt from VIA for providing documentation and
|
||||
technical support.
|
||||
|
||||
|
||||
Module Parameters
|
||||
-----------------
|
||||
|
||||
* uch_config: int Override the BIOS default universal channel (UCH)
|
||||
configuration for channels 1-5.
|
||||
Legal values are in the range of 0-31. Bit 0 maps to
|
||||
UCH1, bit 1 maps to UCH2 and so on. Setting a bit to 1
|
||||
enables the thermal input of that particular UCH and
|
||||
setting a bit to 0 enables the voltage input.
|
||||
|
||||
* int_mode: int Override the BIOS default temperature interrupt mode.
|
||||
The only possible value is 0 which forces interrupt
|
||||
mode 0. In this mode, any pending interrupt is cleared
|
||||
when the status register is read but is regenerated as
|
||||
long as the temperature stays above the hysteresis
|
||||
limit.
|
||||
|
||||
Be aware that overriding BIOS defaults might cause some unwanted side effects!
|
||||
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
The VIA VT1211 Super-I/O chip includes complete hardware monitoring
|
||||
capabilities. It monitors 2 dedicated temperature sensor inputs (temp1 and
|
||||
temp2), 1 dedicated voltage (in5) and 2 fans. Additionally, the chip
|
||||
implements 5 universal input channels (UCH1-5) that can be individually
|
||||
programmed to either monitor a voltage or a temperature.
|
||||
|
||||
This chip also provides manual and automatic control of fan speeds (according
|
||||
to the datasheet). The driver only supports automatic control since the manual
|
||||
mode doesn't seem to work as advertised in the datasheet. In fact I couldn't
|
||||
get manual mode to work at all! Be aware that automatic mode hasn't been
|
||||
tested very well (due to the fact that my EPIA M10000 doesn't have the fans
|
||||
connected to the PWM outputs of the VT1211 :-().
|
||||
|
||||
The following table shows the relationship between the vt1211 inputs and the
|
||||
sysfs nodes.
|
||||
|
||||
Sensor Voltage Mode Temp Mode Default Use (from the datasheet)
|
||||
------ ------------ --------- --------------------------------
|
||||
Reading 1 temp1 Intel thermal diode
|
||||
Reading 3 temp2 Internal thermal diode
|
||||
UCH1/Reading2 in0 temp3 NTC type thermistor
|
||||
UCH2 in1 temp4 +2.5V
|
||||
UCH3 in2 temp5 VccP (processor core)
|
||||
UCH4 in3 temp6 +5V
|
||||
UCH5 in4 temp7 +12V
|
||||
+3.3V in5 Internal VCC (+3.3V)
|
||||
|
||||
|
||||
Voltage Monitoring
|
||||
------------------
|
||||
|
||||
Voltages are sampled by an 8-bit ADC with a LSB of ~10mV. The supported input
|
||||
range is thus from 0 to 2.60V. Voltage values outside of this range need
|
||||
external scaling resistors. This external scaling needs to be compensated for
|
||||
via compute lines in sensors.conf, like:
|
||||
|
||||
compute inx @*(1+R1/R2), @/(1+R1/R2)
|
||||
|
||||
The board level scaling resistors according to VIA's recommendation are as
|
||||
follows. And this is of course totally dependent on the actual board
|
||||
implementation :-) You will have to find documentation for your own
|
||||
motherboard and edit sensors.conf accordingly.
|
||||
|
||||
Expected
|
||||
Voltage R1 R2 Divider Raw Value
|
||||
-----------------------------------------------
|
||||
+2.5V 2K 10K 1.2 2083 mV
|
||||
VccP --- --- 1.0 1400 mV (1)
|
||||
+5V 14K 10K 2.4 2083 mV
|
||||
+12V 47K 10K 5.7 2105 mV
|
||||
+3.3V (int) 2K 3.4K 1.588 3300 mV (2)
|
||||
+3.3V (ext) 6.8K 10K 1.68 1964 mV
|
||||
|
||||
(1) Depending on the CPU (1.4V is for a VIA C3 Nehemiah).
|
||||
(2) R1 and R2 for 3.3V (int) are internal to the VT1211 chip and the driver
|
||||
performs the scaling and returns the properly scaled voltage value.
|
||||
|
||||
Each measured voltage has an associated low and high limit which triggers an
|
||||
alarm when crossed.
|
||||
|
||||
|
||||
Temperature Monitoring
|
||||
----------------------
|
||||
|
||||
Temperatures are reported in millidegree Celsius. Each measured temperature
|
||||
has a high limit which triggers an alarm if crossed. There is an associated
|
||||
hysteresis value with each temperature below which the temperature has to drop
|
||||
before the alarm is cleared (this is only true for interrupt mode 0). The
|
||||
interrupt mode can be forced to 0 in case the BIOS doesn't do it
|
||||
automatically. See the 'Module Parameters' section for details.
|
||||
|
||||
All temperature channels except temp2 are external. Temp2 is the VT1211
|
||||
internal thermal diode and the driver does all the scaling for temp2 and
|
||||
returns the temperature in millidegree Celsius. For the external channels
|
||||
temp1 and temp3-temp7, scaling depends on the board implementation and needs
|
||||
to be performed in userspace via sensors.conf.
|
||||
|
||||
Temp1 is an Intel-type thermal diode which requires the following formula to
|
||||
convert between sysfs readings and real temperatures:
|
||||
|
||||
compute temp1 (@-Offset)/Gain, (@*Gain)+Offset
|
||||
|
||||
According to the VIA VT1211 BIOS porting guide, the following gain and offset
|
||||
values should be used:
|
||||
|
||||
Diode Type Offset Gain
|
||||
---------- ------ ----
|
||||
Intel CPU 88.638 0.9528
|
||||
65.000 0.9686 *)
|
||||
VIA C3 Ezra 83.869 0.9528
|
||||
VIA C3 Ezra-T 73.869 0.9528
|
||||
|
||||
*) This is the formula from the lm_sensors 2.10.0 sensors.conf file. I don't
|
||||
know where it comes from or how it was derived, it's just listed here for
|
||||
completeness.
|
||||
|
||||
Temp3-temp7 support NTC thermistors. For these channels, the driver returns
|
||||
the voltages as seen at the individual pins of UCH1-UCH5. The voltage at the
|
||||
pin (Vpin) is formed by a voltage divider made of the thermistor (Rth) and a
|
||||
scaling resistor (Rs):
|
||||
|
||||
Vpin = 2200 * Rth / (Rs + Rth) (2200 is the ADC max limit of 2200 mV)
|
||||
|
||||
The equation for the thermistor is as follows (google it if you want to know
|
||||
more about it):
|
||||
|
||||
Rth = Ro * exp(B * (1 / T - 1 / To)) (To is 298.15K (25C) and Ro is the
|
||||
nominal resistance at 25C)
|
||||
|
||||
Mingling the above two equations and assuming Rs = Ro and B = 3435 yields the
|
||||
following formula for sensors.conf:
|
||||
|
||||
compute tempx 1 / (1 / 298.15 - (` (2200 / @ - 1)) / 3435) - 273.15,
|
||||
2200 / (1 + (^ (3435 / 298.15 - 3435 / (273.15 + @))))
|
||||
|
||||
|
||||
Fan Speed Control
|
||||
-----------------
|
||||
|
||||
The VT1211 provides 2 programmable PWM outputs to control the speeds of 2
|
||||
fans. Writing a 2 to any of the two pwm[1-2]_enable sysfs nodes will put the
|
||||
PWM controller in automatic mode. There is only a single controller that
|
||||
controls both PWM outputs but each PWM output can be individually enabled and
|
||||
disabled.
|
||||
|
||||
Each PWM has 4 associated distinct output duty-cycles: full, high, low and
|
||||
off. Full and off are internally hard-wired to 255 (100%) and 0 (0%),
|
||||
respectively. High and low can be programmed via
|
||||
pwm[1-2]_auto_point[2-3]_pwm. Each PWM output can be associated with a
|
||||
different thermal input but - and here's the weird part - only one set of
|
||||
thermal thresholds exist that controls both PWMs output duty-cycles. The
|
||||
thermal thresholds are accessible via pwm[1-2]_auto_point[1-4]_temp. Note
|
||||
that even though there are 2 sets of 4 auto points each, they map to the same
|
||||
registers in the VT1211 and programming one set is sufficient (actually only
|
||||
the first set pwm1_auto_point[1-4]_temp is writable, the second set is
|
||||
read-only).
|
||||
|
||||
PWM Auto Point PWM Output Duty-Cycle
|
||||
------------------------------------------------
|
||||
pwm[1-2]_auto_point4_pwm full speed duty-cycle (hard-wired to 255)
|
||||
pwm[1-2]_auto_point3_pwm high speed duty-cycle
|
||||
pwm[1-2]_auto_point2_pwm low speed duty-cycle
|
||||
pwm[1-2]_auto_point1_pwm off duty-cycle (hard-wired to 0)
|
||||
|
||||
Temp Auto Point Thermal Threshold
|
||||
---------------------------------------------
|
||||
pwm[1-2]_auto_point4_temp full speed temp
|
||||
pwm[1-2]_auto_point3_temp high speed temp
|
||||
pwm[1-2]_auto_point2_temp low speed temp
|
||||
pwm[1-2]_auto_point1_temp off temp
|
||||
|
||||
Long story short, the controller implements the following algorithm to set the
|
||||
PWM output duty-cycle based on the input temperature:
|
||||
|
||||
Thermal Threshold Output Duty-Cycle
|
||||
(Rising Temp) (Falling Temp)
|
||||
----------------------------------------------------------
|
||||
full speed duty-cycle full speed duty-cycle
|
||||
full speed temp
|
||||
high speed duty-cycle full speed duty-cycle
|
||||
high speed temp
|
||||
low speed duty-cycle high speed duty-cycle
|
||||
low speed temp
|
||||
off duty-cycle low speed duty-cycle
|
||||
off temp
|
||||
@@ -0,0 +1,85 @@
|
||||
Kernel driver w83627ehf
|
||||
=======================
|
||||
|
||||
Supported chips:
|
||||
* Winbond W83627EHF/EHG (ISA access ONLY)
|
||||
Prefix: 'w83627ehf'
|
||||
Addresses scanned: ISA address retrieved from Super I/O registers
|
||||
Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83627EHF_%20W83627EHGb.pdf
|
||||
|
||||
Authors:
|
||||
Jean Delvare <khali@linux-fr.org>
|
||||
Yuan Mu (Winbond)
|
||||
Rudolf Marek <r.marek@sh.cvut.cz>
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
This driver implements support for the Winbond W83627EHF and W83627EHG
|
||||
super I/O chips. We will refer to them collectively as Winbond chips.
|
||||
|
||||
The chips implement three temperature sensors, five fan rotation
|
||||
speed sensors, ten analog voltage sensors, alarms with beep warnings (control
|
||||
unimplemented), and some automatic fan regulation strategies (plus manual
|
||||
fan control mode).
|
||||
|
||||
Temperatures are measured in degrees Celsius and measurement resolution is 1
|
||||
degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when
|
||||
the temperature gets higher than high limit; it stays on until the temperature
|
||||
falls below the Hysteresis value.
|
||||
|
||||
Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
|
||||
triggered if the rotation speed has dropped below a programmable limit. Fan
|
||||
readings can be divided by a programmable divider (1, 2, 4, 8, 16, 32, 64 or
|
||||
128) to give the readings more range or accuracy. The driver sets the most
|
||||
suitable fan divisor itself. Some fans might not be present because they
|
||||
share pins with other functions.
|
||||
|
||||
Voltage sensors (also known as IN sensors) report their values in millivolts.
|
||||
An alarm is triggered if the voltage has crossed a programmable minimum
|
||||
or maximum limit.
|
||||
|
||||
The driver supports automatic fan control mode known as Thermal Cruise.
|
||||
In this mode, the chip attempts to keep the measured temperature in a
|
||||
predefined temperature range. If the temperature goes out of range, fan
|
||||
is driven slower/faster to reach the predefined range again.
|
||||
|
||||
The mode works for fan1-fan4. Mapping of temperatures to pwm outputs is as
|
||||
follows:
|
||||
|
||||
temp1 -> pwm1
|
||||
temp2 -> pwm2
|
||||
temp3 -> pwm3
|
||||
prog -> pwm4 (the programmable setting is not supported by the driver)
|
||||
|
||||
/sys files
|
||||
----------
|
||||
|
||||
pwm[1-4] - this file stores PWM duty cycle or DC value (fan speed) in range:
|
||||
0 (stop) to 255 (full)
|
||||
|
||||
pwm[1-4]_enable - this file controls mode of fan/temperature control:
|
||||
* 1 Manual Mode, write to pwm file any value 0-255 (full speed)
|
||||
* 2 Thermal Cruise
|
||||
|
||||
Thermal Cruise mode
|
||||
-------------------
|
||||
|
||||
If the temperature is in the range defined by:
|
||||
|
||||
pwm[1-4]_target - set target temperature, unit millidegree Celcius
|
||||
(range 0 - 127000)
|
||||
pwm[1-4]_tolerance - tolerance, unit millidegree Celcius (range 0 - 15000)
|
||||
|
||||
there are no changes to fan speed. Once the temperature leaves the interval,
|
||||
fan speed increases (temp is higher) or decreases if lower than desired.
|
||||
There are defined steps and times, but not exported by the driver yet.
|
||||
|
||||
pwm[1-4]_min_output - minimum fan speed (range 1 - 255), when the temperature
|
||||
is below defined range.
|
||||
pwm[1-4]_stop_time - how many milliseconds [ms] must elapse to switch
|
||||
corresponding fan off. (when the temperature was below
|
||||
defined range).
|
||||
|
||||
Note: last two functions are influenced by other control bits, not yet exported
|
||||
by the driver, so a change might not have any effect.
|
||||
+37
-30
@@ -5,7 +5,7 @@ Supported chips:
|
||||
* Winbond W83791D
|
||||
Prefix: 'w83791d'
|
||||
Addresses scanned: I2C 0x2c - 0x2f
|
||||
Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83791Da.pdf
|
||||
Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83791D_W83791Gb.pdf
|
||||
|
||||
Author: Charles Spirakis <bezaur@gmail.com>
|
||||
|
||||
@@ -20,6 +20,9 @@ Credits:
|
||||
Chunhao Huang <DZShen@Winbond.com.tw>,
|
||||
Rudolf Marek <r.marek@sh.cvut.cz>
|
||||
|
||||
Additional contributors:
|
||||
Sven Anders <anders@anduras.de>
|
||||
|
||||
Module Parameters
|
||||
-----------------
|
||||
|
||||
@@ -46,7 +49,8 @@ Module Parameters
|
||||
Description
|
||||
-----------
|
||||
|
||||
This driver implements support for the Winbond W83791D chip.
|
||||
This driver implements support for the Winbond W83791D chip. The W83791G
|
||||
chip appears to be the same as the W83791D but is lead free.
|
||||
|
||||
Detection of the chip can sometimes be foiled because it can be in an
|
||||
internal state that allows no clean access (Bank with ID register is not
|
||||
@@ -71,34 +75,36 @@ Voltage sensors (also known as IN sensors) report their values in millivolts.
|
||||
An alarm is triggered if the voltage has crossed a programmable minimum
|
||||
or maximum limit.
|
||||
|
||||
Alarms are provided as output from a "realtime status register". The
|
||||
following bits are defined:
|
||||
The bit ordering for the alarm "realtime status register" and the
|
||||
"beep enable registers" are different.
|
||||
|
||||
bit - alarm on:
|
||||
0 - Vcore
|
||||
1 - VINR0
|
||||
2 - +3.3VIN
|
||||
3 - 5VDD
|
||||
4 - temp1
|
||||
5 - temp2
|
||||
6 - fan1
|
||||
7 - fan2
|
||||
8 - +12VIN
|
||||
9 - -12VIN
|
||||
10 - -5VIN
|
||||
11 - fan3
|
||||
12 - chassis
|
||||
13 - temp3
|
||||
14 - VINR1
|
||||
15 - reserved
|
||||
16 - tart1
|
||||
17 - tart2
|
||||
18 - tart3
|
||||
19 - VSB
|
||||
20 - VBAT
|
||||
21 - fan4
|
||||
22 - fan5
|
||||
23 - reserved
|
||||
in0 (VCORE) : alarms: 0x000001 beep_enable: 0x000001
|
||||
in1 (VINR0) : alarms: 0x000002 beep_enable: 0x002000 <== mismatch
|
||||
in2 (+3.3VIN): alarms: 0x000004 beep_enable: 0x000004
|
||||
in3 (5VDD) : alarms: 0x000008 beep_enable: 0x000008
|
||||
in4 (+12VIN) : alarms: 0x000100 beep_enable: 0x000100
|
||||
in5 (-12VIN) : alarms: 0x000200 beep_enable: 0x000200
|
||||
in6 (-5VIN) : alarms: 0x000400 beep_enable: 0x000400
|
||||
in7 (VSB) : alarms: 0x080000 beep_enable: 0x010000 <== mismatch
|
||||
in8 (VBAT) : alarms: 0x100000 beep_enable: 0x020000 <== mismatch
|
||||
in9 (VINR1) : alarms: 0x004000 beep_enable: 0x004000
|
||||
temp1 : alarms: 0x000010 beep_enable: 0x000010
|
||||
temp2 : alarms: 0x000020 beep_enable: 0x000020
|
||||
temp3 : alarms: 0x002000 beep_enable: 0x000002 <== mismatch
|
||||
fan1 : alarms: 0x000040 beep_enable: 0x000040
|
||||
fan2 : alarms: 0x000080 beep_enable: 0x000080
|
||||
fan3 : alarms: 0x000800 beep_enable: 0x000800
|
||||
fan4 : alarms: 0x200000 beep_enable: 0x200000
|
||||
fan5 : alarms: 0x400000 beep_enable: 0x400000
|
||||
tart1 : alarms: 0x010000 beep_enable: 0x040000 <== mismatch
|
||||
tart2 : alarms: 0x020000 beep_enable: 0x080000 <== mismatch
|
||||
tart3 : alarms: 0x040000 beep_enable: 0x100000 <== mismatch
|
||||
case_open : alarms: 0x001000 beep_enable: 0x001000
|
||||
user_enable : alarms: -------- beep_enable: 0x800000
|
||||
|
||||
*** NOTE: It is the responsibility of user-space code to handle the fact
|
||||
that the beep enable and alarm bits are in different positions when using that
|
||||
feature of the chip.
|
||||
|
||||
When an alarm goes off, you can be warned by a beeping signal through your
|
||||
computer speaker. It is possible to enable all beeping globally, or only
|
||||
@@ -109,5 +115,6 @@ often will do no harm, but will return 'old' values.
|
||||
|
||||
W83791D TODO:
|
||||
---------------
|
||||
Provide a patch for per-file alarms as discussed on the mailing list
|
||||
Provide a patch for per-file alarms and beep enables as defined in the hwmon
|
||||
documentation (Documentation/hwmon/sysfs-interface)
|
||||
Provide a patch for smart-fan control (still need appropriate motherboard/fans)
|
||||
|
||||
@@ -3309,6 +3309,12 @@ W: http://linuxtv.org
|
||||
T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git
|
||||
S: Maintained
|
||||
|
||||
VT1211 HARDWARE MONITOR DRIVER
|
||||
P: Juerg Haefliger
|
||||
M: juergh@gmail.com
|
||||
L: lm-sensors@lm-sensors.org
|
||||
S: Maintained
|
||||
|
||||
VT8231 HARDWARE MONITOR DRIVER
|
||||
P: Roger Lucas
|
||||
M: roger@planbit.co.uk
|
||||
|
||||
+36
-15
@@ -53,7 +53,7 @@ config SENSORS_ADM1021
|
||||
|
||||
config SENSORS_ADM1025
|
||||
tristate "Analog Devices ADM1025 and compatibles"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
depends on HWMON && I2C
|
||||
select HWMON_VID
|
||||
help
|
||||
If you say yes here you get support for Analog Devices ADM1025
|
||||
@@ -94,6 +94,16 @@ config SENSORS_ADM9240
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called adm9240.
|
||||
|
||||
config SENSORS_K8TEMP
|
||||
tristate "AMD K8 processor sensor"
|
||||
depends on HWMON && X86 && PCI && EXPERIMENTAL
|
||||
help
|
||||
If you say yes here you get support for the temperature
|
||||
sensor(s) inside your AMD K8 CPU.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called k8temp.
|
||||
|
||||
config SENSORS_ASB100
|
||||
tristate "Asus ASB100 Bach"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
@@ -121,7 +131,7 @@ config SENSORS_ATXP1
|
||||
|
||||
config SENSORS_DS1621
|
||||
tristate "Dallas Semiconductor DS1621 and DS1625"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
depends on HWMON && I2C
|
||||
help
|
||||
If you say yes here you get support for Dallas Semiconductor
|
||||
DS1621 and DS1625 sensor chips.
|
||||
@@ -141,7 +151,7 @@ config SENSORS_F71805F
|
||||
|
||||
config SENSORS_FSCHER
|
||||
tristate "FSC Hermes"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
depends on HWMON && I2C
|
||||
help
|
||||
If you say yes here you get support for Fujitsu Siemens
|
||||
Computers Hermes sensor chips.
|
||||
@@ -151,7 +161,7 @@ config SENSORS_FSCHER
|
||||
|
||||
config SENSORS_FSCPOS
|
||||
tristate "FSC Poseidon"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
depends on HWMON && I2C
|
||||
help
|
||||
If you say yes here you get support for Fujitsu Siemens
|
||||
Computers Poseidon sensor chips.
|
||||
@@ -171,7 +181,7 @@ config SENSORS_GL518SM
|
||||
|
||||
config SENSORS_GL520SM
|
||||
tristate "Genesys Logic GL520SM"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
depends on HWMON && I2C
|
||||
select HWMON_VID
|
||||
help
|
||||
If you say yes here you get support for Genesys Logic GL520SM
|
||||
@@ -186,15 +196,15 @@ config SENSORS_IT87
|
||||
select I2C_ISA
|
||||
select HWMON_VID
|
||||
help
|
||||
If you say yes here you get support for ITE IT87xx sensor chips
|
||||
and clones: SiS960.
|
||||
If you say yes here you get support for ITE IT8705F, IT8712F,
|
||||
IT8716F and IT8718F sensor chips, and the SiS960 clone.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called it87.
|
||||
|
||||
config SENSORS_LM63
|
||||
tristate "National Semiconductor LM63"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
depends on HWMON && I2C
|
||||
help
|
||||
If you say yes here you get support for the National Semiconductor
|
||||
LM63 remote diode digital temperature sensor with integrated fan
|
||||
@@ -231,7 +241,7 @@ config SENSORS_LM75
|
||||
|
||||
config SENSORS_LM77
|
||||
tristate "National Semiconductor LM77"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
depends on HWMON && I2C
|
||||
help
|
||||
If you say yes here you get support for National Semiconductor LM77
|
||||
sensor chips.
|
||||
@@ -241,7 +251,7 @@ config SENSORS_LM77
|
||||
|
||||
config SENSORS_LM78
|
||||
tristate "National Semiconductor LM78 and compatibles"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
depends on HWMON && I2C
|
||||
select I2C_ISA
|
||||
select HWMON_VID
|
||||
help
|
||||
@@ -284,7 +294,7 @@ config SENSORS_LM85
|
||||
|
||||
config SENSORS_LM87
|
||||
tristate "National Semiconductor LM87"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
depends on HWMON && I2C
|
||||
select HWMON_VID
|
||||
help
|
||||
If you say yes here you get support for National Semiconductor LM87
|
||||
@@ -309,7 +319,7 @@ config SENSORS_LM90
|
||||
|
||||
config SENSORS_LM92
|
||||
tristate "National Semiconductor LM92 and compatibles"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
depends on HWMON && I2C
|
||||
help
|
||||
If you say yes here you get support for National Semiconductor LM92
|
||||
and Maxim MAX6635 sensor chips.
|
||||
@@ -319,7 +329,7 @@ config SENSORS_LM92
|
||||
|
||||
config SENSORS_MAX1619
|
||||
tristate "Maxim MAX1619 sensor chip"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
depends on HWMON && I2C
|
||||
help
|
||||
If you say yes here you get support for MAX1619 sensor chip.
|
||||
|
||||
@@ -354,7 +364,7 @@ config SENSORS_SIS5595
|
||||
|
||||
config SENSORS_SMSC47M1
|
||||
tristate "SMSC LPC47M10x and compatibles"
|
||||
depends on HWMON && I2C && EXPERIMENTAL
|
||||
depends on HWMON && I2C
|
||||
select I2C_ISA
|
||||
help
|
||||
If you say yes here you get support for the integrated fan
|
||||
@@ -407,8 +417,19 @@ config SENSORS_VIA686A
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called via686a.
|
||||
|
||||
config SENSORS_VT1211
|
||||
tristate "VIA VT1211"
|
||||
depends on HWMON && EXPERIMENTAL
|
||||
select HWMON_VID
|
||||
help
|
||||
If you say yes here then you get support for hardware monitoring
|
||||
features of the VIA VT1211 Super-I/O chip.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called vt1211.
|
||||
|
||||
config SENSORS_VT8231
|
||||
tristate "VT8231"
|
||||
tristate "VIA VT8231"
|
||||
depends on HWMON && I2C && PCI && EXPERIMENTAL
|
||||
select HWMON_VID
|
||||
select I2C_ISA
|
||||
|
||||
@@ -27,6 +27,7 @@ obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
|
||||
obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o
|
||||
obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o
|
||||
obj-$(CONFIG_SENSORS_IT87) += it87.o
|
||||
obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o
|
||||
obj-$(CONFIG_SENSORS_LM63) += lm63.o
|
||||
obj-$(CONFIG_SENSORS_LM70) += lm70.o
|
||||
obj-$(CONFIG_SENSORS_LM75) += lm75.o
|
||||
@@ -45,6 +46,7 @@ obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
|
||||
obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
|
||||
obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o
|
||||
obj-$(CONFIG_SENSORS_VIA686A) += via686a.o
|
||||
obj-$(CONFIG_SENSORS_VT1211) += vt1211.o
|
||||
obj-$(CONFIG_SENSORS_VT8231) += vt8231.o
|
||||
obj-$(CONFIG_SENSORS_W83627EHF) += w83627ehf.o
|
||||
obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o
|
||||
|
||||
@@ -1354,13 +1354,39 @@ LEAVE_UPDATE:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int abituguru_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
struct abituguru_data *data = platform_get_drvdata(pdev);
|
||||
/* make sure all communications with the uguru are done and no new
|
||||
ones are started */
|
||||
mutex_lock(&data->update_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int abituguru_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct abituguru_data *data = platform_get_drvdata(pdev);
|
||||
/* See if the uGuru is still ready */
|
||||
if (inb_p(data->addr + ABIT_UGURU_DATA) != ABIT_UGURU_STATUS_INPUT)
|
||||
data->uguru_ready = 0;
|
||||
mutex_unlock(&data->update_lock);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define abituguru_suspend NULL
|
||||
#define abituguru_resume NULL
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static struct platform_driver abituguru_driver = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = ABIT_UGURU_NAME,
|
||||
},
|
||||
.probe = abituguru_probe,
|
||||
.remove = __devexit_p(abituguru_remove),
|
||||
.probe = abituguru_probe,
|
||||
.remove = __devexit_p(abituguru_remove),
|
||||
.suspend = abituguru_suspend,
|
||||
.resume = abituguru_resume,
|
||||
};
|
||||
|
||||
static int __init abituguru_detect(void)
|
||||
|
||||
+22
-9
@@ -190,6 +190,21 @@ static int adm1021_attach_adapter(struct i2c_adapter *adapter)
|
||||
return i2c_probe(adapter, &addr_data, adm1021_detect);
|
||||
}
|
||||
|
||||
static struct attribute *adm1021_attributes[] = {
|
||||
&dev_attr_temp1_max.attr,
|
||||
&dev_attr_temp1_min.attr,
|
||||
&dev_attr_temp1_input.attr,
|
||||
&dev_attr_temp2_max.attr,
|
||||
&dev_attr_temp2_min.attr,
|
||||
&dev_attr_temp2_input.attr,
|
||||
&dev_attr_alarms.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group adm1021_group = {
|
||||
.attrs = adm1021_attributes,
|
||||
};
|
||||
|
||||
static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
{
|
||||
int i;
|
||||
@@ -287,22 +302,19 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
adm1021_init_client(new_client);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
if ((err = sysfs_create_group(&new_client->dev.kobj, &adm1021_group)))
|
||||
goto error2;
|
||||
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto error2;
|
||||
goto error3;
|
||||
}
|
||||
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_max);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_min);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp2_max);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp2_min);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp2_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_alarms);
|
||||
|
||||
return 0;
|
||||
|
||||
error3:
|
||||
sysfs_remove_group(&new_client->dev.kobj, &adm1021_group);
|
||||
error2:
|
||||
i2c_detach_client(new_client);
|
||||
error1:
|
||||
@@ -326,6 +338,7 @@ static int adm1021_detach_client(struct i2c_client *client)
|
||||
int err;
|
||||
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
sysfs_remove_group(&client->dev.kobj, &adm1021_group);
|
||||
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
|
||||
+62
-32
@@ -315,6 +315,49 @@ static int adm1025_attach_adapter(struct i2c_adapter *adapter)
|
||||
return i2c_probe(adapter, &addr_data, adm1025_detect);
|
||||
}
|
||||
|
||||
static struct attribute *adm1025_attributes[] = {
|
||||
&dev_attr_in0_input.attr,
|
||||
&dev_attr_in1_input.attr,
|
||||
&dev_attr_in2_input.attr,
|
||||
&dev_attr_in3_input.attr,
|
||||
&dev_attr_in5_input.attr,
|
||||
&dev_attr_in0_min.attr,
|
||||
&dev_attr_in1_min.attr,
|
||||
&dev_attr_in2_min.attr,
|
||||
&dev_attr_in3_min.attr,
|
||||
&dev_attr_in5_min.attr,
|
||||
&dev_attr_in0_max.attr,
|
||||
&dev_attr_in1_max.attr,
|
||||
&dev_attr_in2_max.attr,
|
||||
&dev_attr_in3_max.attr,
|
||||
&dev_attr_in5_max.attr,
|
||||
&dev_attr_temp1_input.attr,
|
||||
&dev_attr_temp2_input.attr,
|
||||
&dev_attr_temp1_min.attr,
|
||||
&dev_attr_temp2_min.attr,
|
||||
&dev_attr_temp1_max.attr,
|
||||
&dev_attr_temp2_max.attr,
|
||||
&dev_attr_alarms.attr,
|
||||
&dev_attr_cpu0_vid.attr,
|
||||
&dev_attr_vrm.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group adm1025_group = {
|
||||
.attrs = adm1025_attributes,
|
||||
};
|
||||
|
||||
static struct attribute *adm1025_attributes_opt[] = {
|
||||
&dev_attr_in4_input.attr,
|
||||
&dev_attr_in4_min.attr,
|
||||
&dev_attr_in4_max.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group adm1025_group_opt = {
|
||||
.attrs = adm1025_attributes_opt,
|
||||
};
|
||||
|
||||
/*
|
||||
* The following function does more than just detection. If detection
|
||||
* succeeds, it also registers the new chip.
|
||||
@@ -415,46 +458,31 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
adm1025_init_client(new_client);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
if ((err = sysfs_create_group(&new_client->dev.kobj, &adm1025_group)))
|
||||
goto exit_detach;
|
||||
}
|
||||
|
||||
device_create_file(&new_client->dev, &dev_attr_in0_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_in1_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_in2_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_in3_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_in5_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_in0_min);
|
||||
device_create_file(&new_client->dev, &dev_attr_in1_min);
|
||||
device_create_file(&new_client->dev, &dev_attr_in2_min);
|
||||
device_create_file(&new_client->dev, &dev_attr_in3_min);
|
||||
device_create_file(&new_client->dev, &dev_attr_in5_min);
|
||||
device_create_file(&new_client->dev, &dev_attr_in0_max);
|
||||
device_create_file(&new_client->dev, &dev_attr_in1_max);
|
||||
device_create_file(&new_client->dev, &dev_attr_in2_max);
|
||||
device_create_file(&new_client->dev, &dev_attr_in3_max);
|
||||
device_create_file(&new_client->dev, &dev_attr_in5_max);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp2_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_min);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp2_min);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_max);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp2_max);
|
||||
device_create_file(&new_client->dev, &dev_attr_alarms);
|
||||
device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
|
||||
device_create_file(&new_client->dev, &dev_attr_vrm);
|
||||
|
||||
/* Pin 11 is either in4 (+12V) or VID4 */
|
||||
if (!(config & 0x20)) {
|
||||
device_create_file(&new_client->dev, &dev_attr_in4_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_in4_min);
|
||||
device_create_file(&new_client->dev, &dev_attr_in4_max);
|
||||
if ((err = device_create_file(&new_client->dev,
|
||||
&dev_attr_in4_input))
|
||||
|| (err = device_create_file(&new_client->dev,
|
||||
&dev_attr_in4_min))
|
||||
|| (err = device_create_file(&new_client->dev,
|
||||
&dev_attr_in4_max)))
|
||||
goto exit_remove;
|
||||
}
|
||||
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_remove;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
exit_remove:
|
||||
sysfs_remove_group(&new_client->dev.kobj, &adm1025_group);
|
||||
sysfs_remove_group(&new_client->dev.kobj, &adm1025_group_opt);
|
||||
exit_detach:
|
||||
i2c_detach_client(new_client);
|
||||
exit_free:
|
||||
@@ -511,6 +539,8 @@ static int adm1025_detach_client(struct i2c_client *client)
|
||||
int err;
|
||||
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
sysfs_remove_group(&client->dev.kobj, &adm1025_group);
|
||||
sysfs_remove_group(&client->dev.kobj, &adm1025_group_opt);
|
||||
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
|
||||
+146
-140
@@ -323,15 +323,6 @@ static int adm1026_attach_adapter(struct i2c_adapter *adapter)
|
||||
return i2c_probe(adapter, &addr_data, adm1026_detect);
|
||||
}
|
||||
|
||||
static int adm1026_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct adm1026_data *data = i2c_get_clientdata(client);
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
i2c_detach_client(client);
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adm1026_read_value(struct i2c_client *client, u8 reg)
|
||||
{
|
||||
int res;
|
||||
@@ -1450,6 +1441,135 @@ static DEVICE_ATTR(temp1_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
|
||||
static DEVICE_ATTR(temp2_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
|
||||
static DEVICE_ATTR(temp3_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);
|
||||
|
||||
static struct attribute *adm1026_attributes[] = {
|
||||
&sensor_dev_attr_in0_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in0_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in0_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in1_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in1_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in2_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in2_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in2_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in3_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in3_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in3_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in4_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in4_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in4_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in5_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in5_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in5_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in6_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in6_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in6_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in7_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in7_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in7_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in8_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in8_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in8_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in9_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in9_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in9_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in10_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in10_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in10_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in11_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in11_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in11_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in12_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in12_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in12_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in13_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in13_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in13_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in14_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in14_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in14_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in15_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in15_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in15_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in16_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in16_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in16_min.dev_attr.attr,
|
||||
&sensor_dev_attr_fan1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan1_div.dev_attr.attr,
|
||||
&sensor_dev_attr_fan1_min.dev_attr.attr,
|
||||
&sensor_dev_attr_fan2_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan2_div.dev_attr.attr,
|
||||
&sensor_dev_attr_fan2_min.dev_attr.attr,
|
||||
&sensor_dev_attr_fan3_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan3_div.dev_attr.attr,
|
||||
&sensor_dev_attr_fan3_min.dev_attr.attr,
|
||||
&sensor_dev_attr_fan4_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan4_div.dev_attr.attr,
|
||||
&sensor_dev_attr_fan4_min.dev_attr.attr,
|
||||
&sensor_dev_attr_fan5_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan5_div.dev_attr.attr,
|
||||
&sensor_dev_attr_fan5_min.dev_attr.attr,
|
||||
&sensor_dev_attr_fan6_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan6_div.dev_attr.attr,
|
||||
&sensor_dev_attr_fan6_min.dev_attr.attr,
|
||||
&sensor_dev_attr_fan7_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan7_div.dev_attr.attr,
|
||||
&sensor_dev_attr_fan7_min.dev_attr.attr,
|
||||
&sensor_dev_attr_fan8_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan8_div.dev_attr.attr,
|
||||
&sensor_dev_attr_fan8_min.dev_attr.attr,
|
||||
&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_temp2_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp2_max.dev_attr.attr,
|
||||
&sensor_dev_attr_temp2_min.dev_attr.attr,
|
||||
&sensor_dev_attr_temp3_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp3_max.dev_attr.attr,
|
||||
&sensor_dev_attr_temp3_min.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_offset.dev_attr.attr,
|
||||
&sensor_dev_attr_temp2_offset.dev_attr.attr,
|
||||
&sensor_dev_attr_temp3_offset.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr,
|
||||
&sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr,
|
||||
&sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr.attr,
|
||||
&sensor_dev_attr_temp2_auto_point1_temp_hyst.dev_attr.attr,
|
||||
&sensor_dev_attr_temp3_auto_point1_temp_hyst.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr,
|
||||
&sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr,
|
||||
&sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_crit.dev_attr.attr,
|
||||
&sensor_dev_attr_temp2_crit.dev_attr.attr,
|
||||
&sensor_dev_attr_temp3_crit.dev_attr.attr,
|
||||
&dev_attr_temp1_crit_enable.attr,
|
||||
&dev_attr_temp2_crit_enable.attr,
|
||||
&dev_attr_temp3_crit_enable.attr,
|
||||
&dev_attr_cpu0_vid.attr,
|
||||
&dev_attr_vrm.attr,
|
||||
&dev_attr_alarms.attr,
|
||||
&dev_attr_alarm_mask.attr,
|
||||
&dev_attr_gpio.attr,
|
||||
&dev_attr_gpio_mask.attr,
|
||||
&dev_attr_pwm1.attr,
|
||||
&dev_attr_pwm2.attr,
|
||||
&dev_attr_pwm3.attr,
|
||||
&dev_attr_pwm1_enable.attr,
|
||||
&dev_attr_pwm2_enable.attr,
|
||||
&dev_attr_pwm3_enable.attr,
|
||||
&dev_attr_temp1_auto_point1_pwm.attr,
|
||||
&dev_attr_temp2_auto_point1_pwm.attr,
|
||||
&dev_attr_temp3_auto_point1_pwm.attr,
|
||||
&dev_attr_temp1_auto_point2_pwm.attr,
|
||||
&dev_attr_temp2_auto_point2_pwm.attr,
|
||||
&dev_attr_temp3_auto_point2_pwm.attr,
|
||||
&dev_attr_analog_out.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group adm1026_group = {
|
||||
.attrs = adm1026_attributes,
|
||||
};
|
||||
|
||||
static int adm1026_detect(struct i2c_adapter *adapter, int address,
|
||||
int kind)
|
||||
{
|
||||
@@ -1554,145 +1674,20 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address,
|
||||
adm1026_init_client(new_client);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
if ((err = sysfs_create_group(&new_client->dev.kobj, &adm1026_group)))
|
||||
goto exitdetach;
|
||||
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exitdetach;
|
||||
goto exitremove;
|
||||
}
|
||||
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in1_max.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in1_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in2_max.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in2_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in3_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in3_max.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in3_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in4_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in4_max.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in4_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in5_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in5_max.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in5_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in6_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in6_max.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in6_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in7_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in7_max.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in7_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in8_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in8_max.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in8_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in9_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in9_max.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in9_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in10_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in10_max.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in10_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in11_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in11_max.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in11_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in12_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in12_max.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in12_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in13_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in13_max.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in13_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in14_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in14_max.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in14_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in15_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in15_max.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in15_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in16_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in16_max.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_in16_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_fan1_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_fan1_div.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_fan1_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_fan2_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_fan2_div.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_fan2_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_fan3_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_fan3_div.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_fan3_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_fan4_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_fan4_div.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_fan4_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_fan5_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_fan5_div.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_fan5_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_fan6_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_fan6_div.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_fan6_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_fan7_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_fan7_div.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_fan7_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_fan8_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_fan8_div.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_fan8_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_temp1_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_temp1_max.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_temp1_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_temp2_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_temp2_max.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_temp2_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_temp3_input.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_temp3_max.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_temp3_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_temp1_offset.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_temp2_offset.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_temp3_offset.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_temp1_auto_point1_temp.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_temp2_auto_point1_temp.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_temp3_auto_point1_temp.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_temp2_auto_point1_temp_hyst.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_temp3_auto_point1_temp_hyst.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_temp1_auto_point2_temp.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_temp2_auto_point2_temp.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_temp3_auto_point2_temp.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_temp1_crit.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_temp2_crit.dev_attr);
|
||||
device_create_file(&new_client->dev, &sensor_dev_attr_temp3_crit.dev_attr);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_crit_enable);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp2_crit_enable);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp3_crit_enable);
|
||||
device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
|
||||
device_create_file(&new_client->dev, &dev_attr_vrm);
|
||||
device_create_file(&new_client->dev, &dev_attr_alarms);
|
||||
device_create_file(&new_client->dev, &dev_attr_alarm_mask);
|
||||
device_create_file(&new_client->dev, &dev_attr_gpio);
|
||||
device_create_file(&new_client->dev, &dev_attr_gpio_mask);
|
||||
device_create_file(&new_client->dev, &dev_attr_pwm1);
|
||||
device_create_file(&new_client->dev, &dev_attr_pwm2);
|
||||
device_create_file(&new_client->dev, &dev_attr_pwm3);
|
||||
device_create_file(&new_client->dev, &dev_attr_pwm1_enable);
|
||||
device_create_file(&new_client->dev, &dev_attr_pwm2_enable);
|
||||
device_create_file(&new_client->dev, &dev_attr_pwm3_enable);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_auto_point1_pwm);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp2_auto_point1_pwm);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp3_auto_point1_pwm);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_auto_point2_pwm);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp2_auto_point2_pwm);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp3_auto_point2_pwm);
|
||||
device_create_file(&new_client->dev, &dev_attr_analog_out);
|
||||
return 0;
|
||||
|
||||
/* Error out and cleanup code */
|
||||
exitremove:
|
||||
sysfs_remove_group(&new_client->dev.kobj, &adm1026_group);
|
||||
exitdetach:
|
||||
i2c_detach_client(new_client);
|
||||
exitfree:
|
||||
@@ -1700,6 +1695,17 @@ exitfree:
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int adm1026_detach_client(struct i2c_client *client)
|
||||
{
|
||||
struct adm1026_data *data = i2c_get_clientdata(client);
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
sysfs_remove_group(&client->dev.kobj, &adm1026_group);
|
||||
i2c_detach_client(client);
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init sm_adm1026_init(void)
|
||||
{
|
||||
return i2c_add_driver(&adm1026_driver);
|
||||
|
||||
+70
-44
@@ -730,6 +730,61 @@ static int adm1031_attach_adapter(struct i2c_adapter *adapter)
|
||||
return i2c_probe(adapter, &addr_data, adm1031_detect);
|
||||
}
|
||||
|
||||
static struct attribute *adm1031_attributes[] = {
|
||||
&dev_attr_fan1_input.attr,
|
||||
&dev_attr_fan1_div.attr,
|
||||
&dev_attr_fan1_min.attr,
|
||||
&dev_attr_pwm1.attr,
|
||||
&dev_attr_auto_fan1_channel.attr,
|
||||
&dev_attr_temp1_input.attr,
|
||||
&dev_attr_temp1_min.attr,
|
||||
&dev_attr_temp1_max.attr,
|
||||
&dev_attr_temp1_crit.attr,
|
||||
&dev_attr_temp2_input.attr,
|
||||
&dev_attr_temp2_min.attr,
|
||||
&dev_attr_temp2_max.attr,
|
||||
&dev_attr_temp2_crit.attr,
|
||||
|
||||
&dev_attr_auto_temp1_off.attr,
|
||||
&dev_attr_auto_temp1_min.attr,
|
||||
&dev_attr_auto_temp1_max.attr,
|
||||
|
||||
&dev_attr_auto_temp2_off.attr,
|
||||
&dev_attr_auto_temp2_min.attr,
|
||||
&dev_attr_auto_temp2_max.attr,
|
||||
|
||||
&dev_attr_auto_fan1_min_pwm.attr,
|
||||
|
||||
&dev_attr_alarms.attr,
|
||||
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group adm1031_group = {
|
||||
.attrs = adm1031_attributes,
|
||||
};
|
||||
|
||||
static struct attribute *adm1031_attributes_opt[] = {
|
||||
&dev_attr_fan2_input.attr,
|
||||
&dev_attr_fan2_div.attr,
|
||||
&dev_attr_fan2_min.attr,
|
||||
&dev_attr_pwm2.attr,
|
||||
&dev_attr_auto_fan2_channel.attr,
|
||||
&dev_attr_temp3_input.attr,
|
||||
&dev_attr_temp3_min.attr,
|
||||
&dev_attr_temp3_max.attr,
|
||||
&dev_attr_temp3_crit.attr,
|
||||
&dev_attr_auto_temp3_off.attr,
|
||||
&dev_attr_auto_temp3_min.attr,
|
||||
&dev_attr_auto_temp3_max.attr,
|
||||
&dev_attr_auto_fan2_min_pwm.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group adm1031_group_opt = {
|
||||
.attrs = adm1031_attributes_opt,
|
||||
};
|
||||
|
||||
/* This function is called by i2c_probe */
|
||||
static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
{
|
||||
@@ -789,57 +844,26 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
adm1031_init_client(new_client);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
if ((err = sysfs_create_group(&new_client->dev.kobj, &adm1031_group)))
|
||||
goto exit_detach;
|
||||
|
||||
if (kind == adm1031) {
|
||||
if ((err = sysfs_create_group(&new_client->dev.kobj,
|
||||
&adm1031_group_opt)))
|
||||
goto exit_remove;
|
||||
}
|
||||
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_detach;
|
||||
}
|
||||
|
||||
device_create_file(&new_client->dev, &dev_attr_fan1_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_fan1_div);
|
||||
device_create_file(&new_client->dev, &dev_attr_fan1_min);
|
||||
device_create_file(&new_client->dev, &dev_attr_pwm1);
|
||||
device_create_file(&new_client->dev, &dev_attr_auto_fan1_channel);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_min);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_max);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_crit);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp2_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp2_min);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp2_max);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp2_crit);
|
||||
|
||||
device_create_file(&new_client->dev, &dev_attr_auto_temp1_off);
|
||||
device_create_file(&new_client->dev, &dev_attr_auto_temp1_min);
|
||||
device_create_file(&new_client->dev, &dev_attr_auto_temp1_max);
|
||||
|
||||
device_create_file(&new_client->dev, &dev_attr_auto_temp2_off);
|
||||
device_create_file(&new_client->dev, &dev_attr_auto_temp2_min);
|
||||
device_create_file(&new_client->dev, &dev_attr_auto_temp2_max);
|
||||
|
||||
device_create_file(&new_client->dev, &dev_attr_auto_fan1_min_pwm);
|
||||
|
||||
device_create_file(&new_client->dev, &dev_attr_alarms);
|
||||
|
||||
if (kind == adm1031) {
|
||||
device_create_file(&new_client->dev, &dev_attr_fan2_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_fan2_div);
|
||||
device_create_file(&new_client->dev, &dev_attr_fan2_min);
|
||||
device_create_file(&new_client->dev, &dev_attr_pwm2);
|
||||
device_create_file(&new_client->dev,
|
||||
&dev_attr_auto_fan2_channel);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp3_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp3_min);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp3_max);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp3_crit);
|
||||
device_create_file(&new_client->dev, &dev_attr_auto_temp3_off);
|
||||
device_create_file(&new_client->dev, &dev_attr_auto_temp3_min);
|
||||
device_create_file(&new_client->dev, &dev_attr_auto_temp3_max);
|
||||
device_create_file(&new_client->dev, &dev_attr_auto_fan2_min_pwm);
|
||||
goto exit_remove;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
exit_remove:
|
||||
sysfs_remove_group(&new_client->dev.kobj, &adm1031_group);
|
||||
sysfs_remove_group(&new_client->dev.kobj, &adm1031_group_opt);
|
||||
exit_detach:
|
||||
i2c_detach_client(new_client);
|
||||
exit_free:
|
||||
@@ -854,6 +878,8 @@ static int adm1031_detach_client(struct i2c_client *client)
|
||||
int ret;
|
||||
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
sysfs_remove_group(&client->dev.kobj, &adm1031_group);
|
||||
sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt);
|
||||
if ((ret = i2c_detach_client(client)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
+46
-59
@@ -465,6 +465,45 @@ static ssize_t chassis_clear(struct device *dev,
|
||||
}
|
||||
static DEVICE_ATTR(chassis_clear, S_IWUSR, NULL, chassis_clear);
|
||||
|
||||
static struct attribute *adm9240_attributes[] = {
|
||||
&sensor_dev_attr_in0_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in0_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in0_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in1_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in1_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in2_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in2_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in2_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in3_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in3_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in3_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in4_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in4_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in4_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in5_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in5_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in5_max.dev_attr.attr,
|
||||
&dev_attr_temp1_input.attr,
|
||||
&sensor_dev_attr_temp1_max.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
|
||||
&sensor_dev_attr_fan1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan1_div.dev_attr.attr,
|
||||
&sensor_dev_attr_fan1_min.dev_attr.attr,
|
||||
&sensor_dev_attr_fan2_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan2_div.dev_attr.attr,
|
||||
&sensor_dev_attr_fan2_min.dev_attr.attr,
|
||||
&dev_attr_alarms.attr,
|
||||
&dev_attr_aout_output.attr,
|
||||
&dev_attr_chassis_clear.attr,
|
||||
&dev_attr_cpu0_vid.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group adm9240_group = {
|
||||
.attrs = adm9240_attributes,
|
||||
};
|
||||
|
||||
|
||||
/*** sensor chip detect and driver install ***/
|
||||
|
||||
@@ -548,72 +587,19 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
adm9240_init_client(new_client);
|
||||
|
||||
/* populate sysfs filesystem */
|
||||
if ((err = sysfs_create_group(&new_client->dev.kobj, &adm9240_group)))
|
||||
goto exit_detach;
|
||||
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_detach;
|
||||
goto exit_remove;
|
||||
}
|
||||
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in0_input.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in0_min.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in0_max.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in1_input.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in1_min.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in1_max.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in2_input.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in2_min.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in2_max.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in3_input.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in3_min.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in3_max.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in4_input.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in4_min.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in4_max.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in5_input.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in5_min.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_in5_max.dev_attr);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_input);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_temp1_max.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_temp1_max_hyst.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_fan1_input.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_fan1_div.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_fan1_min.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_fan2_input.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_fan2_div.dev_attr);
|
||||
device_create_file(&new_client->dev,
|
||||
&sensor_dev_attr_fan2_min.dev_attr);
|
||||
device_create_file(&new_client->dev, &dev_attr_alarms);
|
||||
device_create_file(&new_client->dev, &dev_attr_aout_output);
|
||||
device_create_file(&new_client->dev, &dev_attr_chassis_clear);
|
||||
device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
|
||||
|
||||
return 0;
|
||||
|
||||
exit_remove:
|
||||
sysfs_remove_group(&new_client->dev.kobj, &adm9240_group);
|
||||
exit_detach:
|
||||
i2c_detach_client(new_client);
|
||||
exit_free:
|
||||
@@ -635,6 +621,7 @@ static int adm9240_detach_client(struct i2c_client *client)
|
||||
int err;
|
||||
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
sysfs_remove_group(&client->dev.kobj, &adm9240_group);
|
||||
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
|
||||
+68
-54
@@ -298,12 +298,6 @@ sysfs_in(4);
|
||||
sysfs_in(5);
|
||||
sysfs_in(6);
|
||||
|
||||
#define device_create_file_in(client, offset) do { \
|
||||
device_create_file(&client->dev, &dev_attr_in##offset##_input); \
|
||||
device_create_file(&client->dev, &dev_attr_in##offset##_min); \
|
||||
device_create_file(&client->dev, &dev_attr_in##offset##_max); \
|
||||
} while (0)
|
||||
|
||||
/* 3 Fans */
|
||||
static ssize_t show_fan(struct device *dev, char *buf, int nr)
|
||||
{
|
||||
@@ -421,12 +415,6 @@ sysfs_fan(1);
|
||||
sysfs_fan(2);
|
||||
sysfs_fan(3);
|
||||
|
||||
#define device_create_file_fan(client, offset) do { \
|
||||
device_create_file(&client->dev, &dev_attr_fan##offset##_input); \
|
||||
device_create_file(&client->dev, &dev_attr_fan##offset##_min); \
|
||||
device_create_file(&client->dev, &dev_attr_fan##offset##_div); \
|
||||
} while (0)
|
||||
|
||||
/* 4 Temp. Sensors */
|
||||
static int sprintf_temp_from_reg(u16 reg, char *buf, int nr)
|
||||
{
|
||||
@@ -515,12 +503,6 @@ sysfs_temp(3);
|
||||
sysfs_temp(4);
|
||||
|
||||
/* VID */
|
||||
#define device_create_file_temp(client, num) do { \
|
||||
device_create_file(&client->dev, &dev_attr_temp##num##_input); \
|
||||
device_create_file(&client->dev, &dev_attr_temp##num##_max); \
|
||||
device_create_file(&client->dev, &dev_attr_temp##num##_max_hyst); \
|
||||
} while (0)
|
||||
|
||||
static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct asb100_data *data = asb100_update_device(dev);
|
||||
@@ -528,8 +510,6 @@ static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
|
||||
#define device_create_file_vid(client) \
|
||||
device_create_file(&client->dev, &dev_attr_cpu0_vid)
|
||||
|
||||
/* VRM */
|
||||
static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
@@ -549,8 +529,6 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const
|
||||
|
||||
/* Alarms */
|
||||
static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
|
||||
#define device_create_file_vrm(client) \
|
||||
device_create_file(&client->dev, &dev_attr_vrm);
|
||||
|
||||
static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
@@ -559,8 +537,6 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
|
||||
#define device_create_file_alarms(client) \
|
||||
device_create_file(&client->dev, &dev_attr_alarms)
|
||||
|
||||
/* 1 PWM */
|
||||
static ssize_t show_pwm1(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
@@ -607,10 +583,65 @@ static ssize_t set_pwm_enable1(struct device *dev, struct device_attribute *attr
|
||||
static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm1, set_pwm1);
|
||||
static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
|
||||
show_pwm_enable1, set_pwm_enable1);
|
||||
#define device_create_file_pwm1(client) do { \
|
||||
device_create_file(&new_client->dev, &dev_attr_pwm1); \
|
||||
device_create_file(&new_client->dev, &dev_attr_pwm1_enable); \
|
||||
} while (0)
|
||||
|
||||
static struct attribute *asb100_attributes[] = {
|
||||
&dev_attr_in0_input.attr,
|
||||
&dev_attr_in0_min.attr,
|
||||
&dev_attr_in0_max.attr,
|
||||
&dev_attr_in1_input.attr,
|
||||
&dev_attr_in1_min.attr,
|
||||
&dev_attr_in1_max.attr,
|
||||
&dev_attr_in2_input.attr,
|
||||
&dev_attr_in2_min.attr,
|
||||
&dev_attr_in2_max.attr,
|
||||
&dev_attr_in3_input.attr,
|
||||
&dev_attr_in3_min.attr,
|
||||
&dev_attr_in3_max.attr,
|
||||
&dev_attr_in4_input.attr,
|
||||
&dev_attr_in4_min.attr,
|
||||
&dev_attr_in4_max.attr,
|
||||
&dev_attr_in5_input.attr,
|
||||
&dev_attr_in5_min.attr,
|
||||
&dev_attr_in5_max.attr,
|
||||
&dev_attr_in6_input.attr,
|
||||
&dev_attr_in6_min.attr,
|
||||
&dev_attr_in6_max.attr,
|
||||
|
||||
&dev_attr_fan1_input.attr,
|
||||
&dev_attr_fan1_min.attr,
|
||||
&dev_attr_fan1_div.attr,
|
||||
&dev_attr_fan2_input.attr,
|
||||
&dev_attr_fan2_min.attr,
|
||||
&dev_attr_fan2_div.attr,
|
||||
&dev_attr_fan3_input.attr,
|
||||
&dev_attr_fan3_min.attr,
|
||||
&dev_attr_fan3_div.attr,
|
||||
|
||||
&dev_attr_temp1_input.attr,
|
||||
&dev_attr_temp1_max.attr,
|
||||
&dev_attr_temp1_max_hyst.attr,
|
||||
&dev_attr_temp2_input.attr,
|
||||
&dev_attr_temp2_max.attr,
|
||||
&dev_attr_temp2_max_hyst.attr,
|
||||
&dev_attr_temp3_input.attr,
|
||||
&dev_attr_temp3_max.attr,
|
||||
&dev_attr_temp3_max_hyst.attr,
|
||||
&dev_attr_temp4_input.attr,
|
||||
&dev_attr_temp4_max.attr,
|
||||
&dev_attr_temp4_max_hyst.attr,
|
||||
|
||||
&dev_attr_cpu0_vid.attr,
|
||||
&dev_attr_vrm.attr,
|
||||
&dev_attr_alarms.attr,
|
||||
&dev_attr_pwm1.attr,
|
||||
&dev_attr_pwm1_enable.attr,
|
||||
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group asb100_group = {
|
||||
.attrs = asb100_attributes,
|
||||
};
|
||||
|
||||
/* This function is called when:
|
||||
asb100_driver is inserted (when this module is loaded), for each
|
||||
@@ -810,38 +841,19 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
data->fan_min[2] = asb100_read_value(new_client, ASB100_REG_FAN_MIN(2));
|
||||
|
||||
/* Register sysfs hooks */
|
||||
if ((err = sysfs_create_group(&new_client->dev.kobj, &asb100_group)))
|
||||
goto ERROR3;
|
||||
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto ERROR3;
|
||||
goto ERROR4;
|
||||
}
|
||||
|
||||
device_create_file_in(new_client, 0);
|
||||
device_create_file_in(new_client, 1);
|
||||
device_create_file_in(new_client, 2);
|
||||
device_create_file_in(new_client, 3);
|
||||
device_create_file_in(new_client, 4);
|
||||
device_create_file_in(new_client, 5);
|
||||
device_create_file_in(new_client, 6);
|
||||
|
||||
device_create_file_fan(new_client, 1);
|
||||
device_create_file_fan(new_client, 2);
|
||||
device_create_file_fan(new_client, 3);
|
||||
|
||||
device_create_file_temp(new_client, 1);
|
||||
device_create_file_temp(new_client, 2);
|
||||
device_create_file_temp(new_client, 3);
|
||||
device_create_file_temp(new_client, 4);
|
||||
|
||||
device_create_file_vid(new_client);
|
||||
device_create_file_vrm(new_client);
|
||||
|
||||
device_create_file_alarms(new_client);
|
||||
|
||||
device_create_file_pwm1(new_client);
|
||||
|
||||
return 0;
|
||||
|
||||
ERROR4:
|
||||
sysfs_remove_group(&new_client->dev.kobj, &asb100_group);
|
||||
ERROR3:
|
||||
i2c_detach_client(data->lm75[1]);
|
||||
i2c_detach_client(data->lm75[0]);
|
||||
@@ -861,8 +873,10 @@ static int asb100_detach_client(struct i2c_client *client)
|
||||
int err;
|
||||
|
||||
/* main client */
|
||||
if (data)
|
||||
if (data) {
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
sysfs_remove_group(&client->dev.kobj, &asb100_group);
|
||||
}
|
||||
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
|
||||
+21
-7
@@ -27,6 +27,7 @@
|
||||
#include <linux/hwmon-vid.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("System voltages control via Attansic ATXP1");
|
||||
@@ -116,8 +117,7 @@ static ssize_t atxp1_storevcore(struct device *dev, struct device_attribute *att
|
||||
{
|
||||
struct atxp1_data *data;
|
||||
struct i2c_client *client;
|
||||
char vid;
|
||||
char cvid;
|
||||
int vid, cvid;
|
||||
unsigned int vcore;
|
||||
|
||||
client = to_i2c_client(dev);
|
||||
@@ -251,6 +251,17 @@ static ssize_t atxp1_storegpio2(struct device *dev, struct device_attribute *att
|
||||
*/
|
||||
static DEVICE_ATTR(gpio2, S_IRUGO | S_IWUSR, atxp1_showgpio2, atxp1_storegpio2);
|
||||
|
||||
static struct attribute *atxp1_attributes[] = {
|
||||
&dev_attr_gpio1.attr,
|
||||
&dev_attr_gpio2.attr,
|
||||
&dev_attr_cpu0_vid.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group atxp1_group = {
|
||||
.attrs = atxp1_attributes,
|
||||
};
|
||||
|
||||
|
||||
static int atxp1_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
@@ -320,21 +331,23 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
goto exit_free;
|
||||
}
|
||||
|
||||
/* Register sysfs hooks */
|
||||
if ((err = sysfs_create_group(&new_client->dev.kobj, &atxp1_group)))
|
||||
goto exit_detach;
|
||||
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_detach;
|
||||
goto exit_remove_files;
|
||||
}
|
||||
|
||||
device_create_file(&new_client->dev, &dev_attr_gpio1);
|
||||
device_create_file(&new_client->dev, &dev_attr_gpio2);
|
||||
device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
|
||||
|
||||
dev_info(&new_client->dev, "Using VRM: %d.%d\n",
|
||||
data->vrm / 10, data->vrm % 10);
|
||||
|
||||
return 0;
|
||||
|
||||
exit_remove_files:
|
||||
sysfs_remove_group(&new_client->dev.kobj, &atxp1_group);
|
||||
exit_detach:
|
||||
i2c_detach_client(new_client);
|
||||
exit_free:
|
||||
@@ -349,6 +362,7 @@ static int atxp1_detach_client(struct i2c_client * client)
|
||||
int err;
|
||||
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
sysfs_remove_group(&client->dev.kobj, &atxp1_group);
|
||||
|
||||
err = i2c_detach_client(client);
|
||||
|
||||
|
||||
+20
-8
@@ -29,6 +29,7 @@
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include "lm75.h"
|
||||
|
||||
/* Addresses to scan */
|
||||
@@ -178,6 +179,18 @@ static DEVICE_ATTR(temp1_input, S_IRUGO , show_temp, NULL);
|
||||
static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO , show_temp_min, set_temp_min);
|
||||
static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max);
|
||||
|
||||
static struct attribute *ds1621_attributes[] = {
|
||||
&dev_attr_temp1_input.attr,
|
||||
&dev_attr_temp1_min.attr,
|
||||
&dev_attr_temp1_max.attr,
|
||||
&dev_attr_alarms.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group ds1621_group = {
|
||||
.attrs = ds1621_attributes,
|
||||
};
|
||||
|
||||
|
||||
static int ds1621_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
@@ -253,21 +266,19 @@ static int ds1621_detect(struct i2c_adapter *adapter, int address,
|
||||
ds1621_init_client(new_client);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
if ((err = sysfs_create_group(&new_client->dev.kobj, &ds1621_group)))
|
||||
goto exit_detach;
|
||||
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_detach;
|
||||
goto exit_remove_files;
|
||||
}
|
||||
|
||||
device_create_file(&new_client->dev, &dev_attr_alarms);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_min);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_max);
|
||||
|
||||
return 0;
|
||||
|
||||
/* OK, this is not exactly good programming practice, usually. But it is
|
||||
very code-efficient in this case. */
|
||||
exit_remove_files:
|
||||
sysfs_remove_group(&new_client->dev.kobj, &ds1621_group);
|
||||
exit_detach:
|
||||
i2c_detach_client(new_client);
|
||||
exit_free:
|
||||
@@ -282,6 +293,7 @@ static int ds1621_detach_client(struct i2c_client *client)
|
||||
int err;
|
||||
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
sysfs_remove_group(&client->dev.kobj, &ds1621_group);
|
||||
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
|
||||
+221
-115
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* f71805f.c - driver for the Fintek F71805F/FG Super-I/O chip integrated
|
||||
* hardware monitoring features
|
||||
* Copyright (C) 2005 Jean Delvare <khali@linux-fr.org>
|
||||
* Copyright (C) 2005-2006 Jean Delvare <khali@linux-fr.org>
|
||||
*
|
||||
* The F71805F/FG is a LPC Super-I/O chip made by Fintek. It integrates
|
||||
* complete hardware monitoring features: voltage, fan and temperature
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
static struct platform_device *pdev;
|
||||
@@ -147,7 +148,7 @@ struct f71805f_data {
|
||||
u8 temp_high[3];
|
||||
u8 temp_hyst[3];
|
||||
u8 temp_mode;
|
||||
u8 alarms[3];
|
||||
unsigned long alarms;
|
||||
};
|
||||
|
||||
static inline long in_from_reg(u8 reg)
|
||||
@@ -311,10 +312,9 @@ static struct f71805f_data *f71805f_update_device(struct device *dev)
|
||||
data->temp[nr] = f71805f_read8(data,
|
||||
F71805F_REG_TEMP(nr));
|
||||
}
|
||||
for (nr = 0; nr < 3; nr++) {
|
||||
data->alarms[nr] = f71805f_read8(data,
|
||||
F71805F_REG_STATUS(nr));
|
||||
}
|
||||
data->alarms = f71805f_read8(data, F71805F_REG_STATUS(0))
|
||||
+ (f71805f_read8(data, F71805F_REG_STATUS(1)) << 8)
|
||||
+ (f71805f_read8(data, F71805F_REG_STATUS(2)) << 16);
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
@@ -557,8 +557,7 @@ static ssize_t show_alarms_in(struct device *dev, struct device_attribute
|
||||
{
|
||||
struct f71805f_data *data = f71805f_update_device(dev);
|
||||
|
||||
return sprintf(buf, "%d\n", data->alarms[0] |
|
||||
((data->alarms[1] & 0x01) << 8));
|
||||
return sprintf(buf, "%lu\n", data->alarms & 0x1ff);
|
||||
}
|
||||
|
||||
static ssize_t show_alarms_fan(struct device *dev, struct device_attribute
|
||||
@@ -566,7 +565,7 @@ static ssize_t show_alarms_fan(struct device *dev, struct device_attribute
|
||||
{
|
||||
struct f71805f_data *data = f71805f_update_device(dev);
|
||||
|
||||
return sprintf(buf, "%d\n", data->alarms[2] & 0x07);
|
||||
return sprintf(buf, "%lu\n", (data->alarms >> 16) & 0x07);
|
||||
}
|
||||
|
||||
static ssize_t show_alarms_temp(struct device *dev, struct device_attribute
|
||||
@@ -574,7 +573,17 @@ static ssize_t show_alarms_temp(struct device *dev, struct device_attribute
|
||||
{
|
||||
struct f71805f_data *data = f71805f_update_device(dev);
|
||||
|
||||
return sprintf(buf, "%d\n", (data->alarms[1] >> 3) & 0x07);
|
||||
return sprintf(buf, "%lu\n", (data->alarms >> 11) & 0x07);
|
||||
}
|
||||
|
||||
static ssize_t show_alarm(struct device *dev, struct device_attribute
|
||||
*devattr, char *buf)
|
||||
{
|
||||
struct f71805f_data *data = f71805f_update_device(dev);
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
int bitnr = attr->index;
|
||||
|
||||
return sprintf(buf, "%lu\n", (data->alarms >> bitnr) & 1);
|
||||
}
|
||||
|
||||
static ssize_t show_name(struct device *dev, struct device_attribute
|
||||
@@ -585,88 +594,189 @@ static ssize_t show_name(struct device *dev, struct device_attribute
|
||||
return sprintf(buf, "%s\n", data->name);
|
||||
}
|
||||
|
||||
static struct device_attribute f71805f_dev_attr[] = {
|
||||
__ATTR(in0_input, S_IRUGO, show_in0, NULL),
|
||||
__ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max),
|
||||
__ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min),
|
||||
__ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL),
|
||||
__ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL),
|
||||
__ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL),
|
||||
__ATTR(name, S_IRUGO, show_name, NULL),
|
||||
static DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL);
|
||||
static DEVICE_ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max);
|
||||
static DEVICE_ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min);
|
||||
static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1);
|
||||
static SENSOR_DEVICE_ATTR(in1_max, S_IRUGO | S_IWUSR,
|
||||
show_in_max, set_in_max, 1);
|
||||
static SENSOR_DEVICE_ATTR(in1_min, S_IRUGO | S_IWUSR,
|
||||
show_in_min, set_in_min, 1);
|
||||
static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 2);
|
||||
static SENSOR_DEVICE_ATTR(in2_max, S_IRUGO | S_IWUSR,
|
||||
show_in_max, set_in_max, 2);
|
||||
static SENSOR_DEVICE_ATTR(in2_min, S_IRUGO | S_IWUSR,
|
||||
show_in_min, set_in_min, 2);
|
||||
static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 3);
|
||||
static SENSOR_DEVICE_ATTR(in3_max, S_IRUGO | S_IWUSR,
|
||||
show_in_max, set_in_max, 3);
|
||||
static SENSOR_DEVICE_ATTR(in3_min, S_IRUGO | S_IWUSR,
|
||||
show_in_min, set_in_min, 3);
|
||||
static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 4);
|
||||
static SENSOR_DEVICE_ATTR(in4_max, S_IRUGO | S_IWUSR,
|
||||
show_in_max, set_in_max, 4);
|
||||
static SENSOR_DEVICE_ATTR(in4_min, S_IRUGO | S_IWUSR,
|
||||
show_in_min, set_in_min, 4);
|
||||
static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_in, NULL, 5);
|
||||
static SENSOR_DEVICE_ATTR(in5_max, S_IRUGO | S_IWUSR,
|
||||
show_in_max, set_in_max, 5);
|
||||
static SENSOR_DEVICE_ATTR(in5_min, S_IRUGO | S_IWUSR,
|
||||
show_in_min, set_in_min, 5);
|
||||
static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_in, NULL, 6);
|
||||
static SENSOR_DEVICE_ATTR(in6_max, S_IRUGO | S_IWUSR,
|
||||
show_in_max, set_in_max, 6);
|
||||
static SENSOR_DEVICE_ATTR(in6_min, S_IRUGO | S_IWUSR,
|
||||
show_in_min, set_in_min, 6);
|
||||
static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_in, NULL, 7);
|
||||
static SENSOR_DEVICE_ATTR(in7_max, S_IRUGO | S_IWUSR,
|
||||
show_in_max, set_in_max, 7);
|
||||
static SENSOR_DEVICE_ATTR(in7_min, S_IRUGO | S_IWUSR,
|
||||
show_in_min, set_in_min, 7);
|
||||
static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_in, NULL, 8);
|
||||
static SENSOR_DEVICE_ATTR(in8_max, S_IRUGO | S_IWUSR,
|
||||
show_in_max, set_in_max, 8);
|
||||
static SENSOR_DEVICE_ATTR(in8_min, S_IRUGO | S_IWUSR,
|
||||
show_in_min, set_in_min, 8);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
|
||||
static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR,
|
||||
show_fan_min, set_fan_min, 0);
|
||||
static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
|
||||
static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO | S_IWUSR,
|
||||
show_fan_min, set_fan_min, 1);
|
||||
static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
|
||||
static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO | S_IWUSR,
|
||||
show_fan_min, set_fan_min, 2);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
|
||||
static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR,
|
||||
show_temp_max, set_temp_max, 0);
|
||||
static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR,
|
||||
show_temp_hyst, set_temp_hyst, 0);
|
||||
static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0);
|
||||
static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
|
||||
static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR,
|
||||
show_temp_max, set_temp_max, 1);
|
||||
static SENSOR_DEVICE_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR,
|
||||
show_temp_hyst, set_temp_hyst, 1);
|
||||
static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1);
|
||||
static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
|
||||
static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO | S_IWUSR,
|
||||
show_temp_max, set_temp_max, 2);
|
||||
static SENSOR_DEVICE_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR,
|
||||
show_temp_hyst, set_temp_hyst, 2);
|
||||
static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
|
||||
static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
|
||||
static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
|
||||
static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
|
||||
static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 4);
|
||||
static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 5);
|
||||
static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 6);
|
||||
static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 7);
|
||||
static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 8);
|
||||
static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 11);
|
||||
static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 12);
|
||||
static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13);
|
||||
static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 16);
|
||||
static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 17);
|
||||
static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 18);
|
||||
static DEVICE_ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL);
|
||||
static DEVICE_ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL);
|
||||
static DEVICE_ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL);
|
||||
|
||||
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
|
||||
|
||||
static struct attribute *f71805f_attributes[] = {
|
||||
&dev_attr_in0_input.attr,
|
||||
&dev_attr_in0_max.attr,
|
||||
&dev_attr_in0_min.attr,
|
||||
&sensor_dev_attr_in1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in1_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in1_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in2_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in2_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in2_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in3_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in3_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in3_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in4_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in4_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in4_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in5_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in5_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in5_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in6_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in6_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in6_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in7_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in7_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in7_min.dev_attr.attr,
|
||||
&sensor_dev_attr_in8_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in8_max.dev_attr.attr,
|
||||
&sensor_dev_attr_in8_min.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_temp1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_max.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_type.dev_attr.attr,
|
||||
&sensor_dev_attr_temp2_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp2_max.dev_attr.attr,
|
||||
&sensor_dev_attr_temp2_max_hyst.dev_attr.attr,
|
||||
&sensor_dev_attr_temp2_type.dev_attr.attr,
|
||||
&sensor_dev_attr_temp3_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp3_max.dev_attr.attr,
|
||||
&sensor_dev_attr_temp3_max_hyst.dev_attr.attr,
|
||||
&sensor_dev_attr_temp3_type.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_in0_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_in1_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_in2_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_in3_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_in4_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_in5_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_in6_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_in7_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_in8_alarm.dev_attr.attr,
|
||||
&dev_attr_alarms_in.attr,
|
||||
&sensor_dev_attr_temp1_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_temp2_alarm.dev_attr.attr,
|
||||
&sensor_dev_attr_temp3_alarm.dev_attr.attr,
|
||||
&dev_attr_alarms_temp.attr,
|
||||
&dev_attr_alarms_fan.attr,
|
||||
|
||||
&dev_attr_name.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct sensor_device_attribute f71805f_sensor_attr[] = {
|
||||
SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1),
|
||||
SENSOR_ATTR(in1_max, S_IRUGO | S_IWUSR,
|
||||
show_in_max, set_in_max, 1),
|
||||
SENSOR_ATTR(in1_min, S_IRUGO | S_IWUSR,
|
||||
show_in_min, set_in_min, 1),
|
||||
SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2),
|
||||
SENSOR_ATTR(in2_max, S_IRUGO | S_IWUSR,
|
||||
show_in_max, set_in_max, 2),
|
||||
SENSOR_ATTR(in2_min, S_IRUGO | S_IWUSR,
|
||||
show_in_min, set_in_min, 2),
|
||||
SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3),
|
||||
SENSOR_ATTR(in3_max, S_IRUGO | S_IWUSR,
|
||||
show_in_max, set_in_max, 3),
|
||||
SENSOR_ATTR(in3_min, S_IRUGO | S_IWUSR,
|
||||
show_in_min, set_in_min, 3),
|
||||
SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4),
|
||||
SENSOR_ATTR(in4_max, S_IRUGO | S_IWUSR,
|
||||
show_in_max, set_in_max, 4),
|
||||
SENSOR_ATTR(in4_min, S_IRUGO | S_IWUSR,
|
||||
show_in_min, set_in_min, 4),
|
||||
SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5),
|
||||
SENSOR_ATTR(in5_max, S_IRUGO | S_IWUSR,
|
||||
show_in_max, set_in_max, 5),
|
||||
SENSOR_ATTR(in5_min, S_IRUGO | S_IWUSR,
|
||||
show_in_min, set_in_min, 5),
|
||||
SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6),
|
||||
SENSOR_ATTR(in6_max, S_IRUGO | S_IWUSR,
|
||||
show_in_max, set_in_max, 6),
|
||||
SENSOR_ATTR(in6_min, S_IRUGO | S_IWUSR,
|
||||
show_in_min, set_in_min, 6),
|
||||
SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7),
|
||||
SENSOR_ATTR(in7_max, S_IRUGO | S_IWUSR,
|
||||
show_in_max, set_in_max, 7),
|
||||
SENSOR_ATTR(in7_min, S_IRUGO | S_IWUSR,
|
||||
show_in_min, set_in_min, 7),
|
||||
SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8),
|
||||
SENSOR_ATTR(in8_max, S_IRUGO | S_IWUSR,
|
||||
show_in_max, set_in_max, 8),
|
||||
SENSOR_ATTR(in8_min, S_IRUGO | S_IWUSR,
|
||||
show_in_min, set_in_min, 8),
|
||||
|
||||
SENSOR_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0),
|
||||
SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR,
|
||||
show_temp_max, set_temp_max, 0),
|
||||
SENSOR_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR,
|
||||
show_temp_hyst, set_temp_hyst, 0),
|
||||
SENSOR_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0),
|
||||
SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1),
|
||||
SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR,
|
||||
show_temp_max, set_temp_max, 1),
|
||||
SENSOR_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR,
|
||||
show_temp_hyst, set_temp_hyst, 1),
|
||||
SENSOR_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1),
|
||||
SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2),
|
||||
SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR,
|
||||
show_temp_max, set_temp_max, 2),
|
||||
SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR,
|
||||
show_temp_hyst, set_temp_hyst, 2),
|
||||
SENSOR_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2),
|
||||
static const struct attribute_group f71805f_group = {
|
||||
.attrs = f71805f_attributes,
|
||||
};
|
||||
|
||||
static struct sensor_device_attribute f71805f_fan_attr[] = {
|
||||
SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0),
|
||||
SENSOR_ATTR(fan1_min, S_IRUGO | S_IWUSR,
|
||||
show_fan_min, set_fan_min, 0),
|
||||
SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1),
|
||||
SENSOR_ATTR(fan2_min, S_IRUGO | S_IWUSR,
|
||||
show_fan_min, set_fan_min, 1),
|
||||
SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2),
|
||||
SENSOR_ATTR(fan3_min, S_IRUGO | S_IWUSR,
|
||||
show_fan_min, set_fan_min, 2),
|
||||
static struct attribute *f71805f_attributes_fan[3][4] = {
|
||||
{
|
||||
&sensor_dev_attr_fan1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan1_min.dev_attr.attr,
|
||||
&sensor_dev_attr_fan1_alarm.dev_attr.attr,
|
||||
NULL
|
||||
}, {
|
||||
&sensor_dev_attr_fan2_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan2_min.dev_attr.attr,
|
||||
&sensor_dev_attr_fan2_alarm.dev_attr.attr,
|
||||
NULL
|
||||
}, {
|
||||
&sensor_dev_attr_fan3_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan3_min.dev_attr.attr,
|
||||
&sensor_dev_attr_fan3_alarm.dev_attr.attr,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
static const struct attribute_group f71805f_group_fan[3] = {
|
||||
{ .attrs = f71805f_attributes_fan[0] },
|
||||
{ .attrs = f71805f_attributes_fan[1] },
|
||||
{ .attrs = f71805f_attributes_fan[2] },
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -714,43 +824,35 @@ static int __devinit f71805f_probe(struct platform_device *pdev)
|
||||
|
||||
platform_set_drvdata(pdev, data);
|
||||
|
||||
data->class_dev = hwmon_device_register(&pdev->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
dev_err(&pdev->dev, "Class registration failed (%d)\n", err);
|
||||
goto exit_free;
|
||||
}
|
||||
|
||||
/* Initialize the F71805F chip */
|
||||
f71805f_init_device(data);
|
||||
|
||||
/* Register sysfs interface files */
|
||||
for (i = 0; i < ARRAY_SIZE(f71805f_dev_attr); i++) {
|
||||
err = device_create_file(&pdev->dev, &f71805f_dev_attr[i]);
|
||||
if (err)
|
||||
goto exit_class;
|
||||
}
|
||||
for (i = 0; i < ARRAY_SIZE(f71805f_sensor_attr); i++) {
|
||||
err = device_create_file(&pdev->dev,
|
||||
&f71805f_sensor_attr[i].dev_attr);
|
||||
if (err)
|
||||
goto exit_class;
|
||||
}
|
||||
for (i = 0; i < ARRAY_SIZE(f71805f_fan_attr); i++) {
|
||||
if (!(data->fan_enabled & (1 << (i / 2))))
|
||||
if ((err = sysfs_create_group(&pdev->dev.kobj, &f71805f_group)))
|
||||
goto exit_free;
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (!(data->fan_enabled & (1 << i)))
|
||||
continue;
|
||||
err = device_create_file(&pdev->dev,
|
||||
&f71805f_fan_attr[i].dev_attr);
|
||||
if (err)
|
||||
goto exit_class;
|
||||
if ((err = sysfs_create_group(&pdev->dev.kobj,
|
||||
&f71805f_group_fan[i])))
|
||||
goto exit_remove_files;
|
||||
}
|
||||
|
||||
data->class_dev = hwmon_device_register(&pdev->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
dev_err(&pdev->dev, "Class registration failed (%d)\n", err);
|
||||
goto exit_remove_files;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
exit_class:
|
||||
dev_err(&pdev->dev, "Sysfs interface creation failed\n");
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
exit_remove_files:
|
||||
sysfs_remove_group(&pdev->dev.kobj, &f71805f_group);
|
||||
for (i = 0; i < 3; i++)
|
||||
sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_fan[i]);
|
||||
exit_free:
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
kfree(data);
|
||||
exit:
|
||||
return err;
|
||||
@@ -759,9 +861,13 @@ exit:
|
||||
static int __devexit f71805f_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct f71805f_data *data = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
sysfs_remove_group(&pdev->dev.kobj, &f71805f_group);
|
||||
for (i = 0; i < 3; i++)
|
||||
sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_fan[i]);
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
|
||||
+41
-53
@@ -34,6 +34,7 @@
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
|
||||
/*
|
||||
* Addresses to scan
|
||||
@@ -240,47 +241,45 @@ sysfs_alarms(FSCHER_REG_EVENTS)
|
||||
sysfs_control(FSCHER_REG_CONTROL)
|
||||
sysfs_watchdog(FSCHER_REG_WDOG_CONTROL, FSCHER_REG_WDOG_STATE, FSCHER_REG_WDOG_PRESET)
|
||||
|
||||
#define device_create_file_fan(client, offset) \
|
||||
do { \
|
||||
device_create_file(&client->dev, &dev_attr_fan##offset##_status); \
|
||||
device_create_file(&client->dev, &dev_attr_pwm##offset); \
|
||||
device_create_file(&client->dev, &dev_attr_fan##offset##_div); \
|
||||
device_create_file(&client->dev, &dev_attr_fan##offset##_input); \
|
||||
} while (0)
|
||||
static struct attribute *fscher_attributes[] = {
|
||||
&dev_attr_revision.attr,
|
||||
&dev_attr_alarms.attr,
|
||||
&dev_attr_control.attr,
|
||||
|
||||
#define device_create_file_temp(client, offset) \
|
||||
do { \
|
||||
device_create_file(&client->dev, &dev_attr_temp##offset##_status); \
|
||||
device_create_file(&client->dev, &dev_attr_temp##offset##_input); \
|
||||
} while (0)
|
||||
&dev_attr_watchdog_status.attr,
|
||||
&dev_attr_watchdog_control.attr,
|
||||
&dev_attr_watchdog_preset.attr,
|
||||
|
||||
#define device_create_file_in(client, offset) \
|
||||
do { \
|
||||
device_create_file(&client->dev, &dev_attr_in##offset##_input); \
|
||||
} while (0)
|
||||
&dev_attr_in0_input.attr,
|
||||
&dev_attr_in1_input.attr,
|
||||
&dev_attr_in2_input.attr,
|
||||
|
||||
#define device_create_file_revision(client) \
|
||||
do { \
|
||||
device_create_file(&client->dev, &dev_attr_revision); \
|
||||
} while (0)
|
||||
&dev_attr_fan1_status.attr,
|
||||
&dev_attr_fan1_div.attr,
|
||||
&dev_attr_fan1_input.attr,
|
||||
&dev_attr_pwm1.attr,
|
||||
&dev_attr_fan2_status.attr,
|
||||
&dev_attr_fan2_div.attr,
|
||||
&dev_attr_fan2_input.attr,
|
||||
&dev_attr_pwm2.attr,
|
||||
&dev_attr_fan3_status.attr,
|
||||
&dev_attr_fan3_div.attr,
|
||||
&dev_attr_fan3_input.attr,
|
||||
&dev_attr_pwm3.attr,
|
||||
|
||||
#define device_create_file_alarms(client) \
|
||||
do { \
|
||||
device_create_file(&client->dev, &dev_attr_alarms); \
|
||||
} while (0)
|
||||
&dev_attr_temp1_status.attr,
|
||||
&dev_attr_temp1_input.attr,
|
||||
&dev_attr_temp2_status.attr,
|
||||
&dev_attr_temp2_input.attr,
|
||||
&dev_attr_temp3_status.attr,
|
||||
&dev_attr_temp3_input.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
#define device_create_file_control(client) \
|
||||
do { \
|
||||
device_create_file(&client->dev, &dev_attr_control); \
|
||||
} while (0)
|
||||
static const struct attribute_group fscher_group = {
|
||||
.attrs = fscher_attributes,
|
||||
};
|
||||
|
||||
#define device_create_file_watchdog(client) \
|
||||
do { \
|
||||
device_create_file(&client->dev, &dev_attr_watchdog_status); \
|
||||
device_create_file(&client->dev, &dev_attr_watchdog_control); \
|
||||
device_create_file(&client->dev, &dev_attr_watchdog_preset); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Real code
|
||||
*/
|
||||
@@ -342,31 +341,19 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
fscher_init_client(new_client);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
if ((err = sysfs_create_group(&new_client->dev.kobj, &fscher_group)))
|
||||
goto exit_detach;
|
||||
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_detach;
|
||||
goto exit_remove_files;
|
||||
}
|
||||
|
||||
device_create_file_revision(new_client);
|
||||
device_create_file_alarms(new_client);
|
||||
device_create_file_control(new_client);
|
||||
device_create_file_watchdog(new_client);
|
||||
|
||||
device_create_file_in(new_client, 0);
|
||||
device_create_file_in(new_client, 1);
|
||||
device_create_file_in(new_client, 2);
|
||||
|
||||
device_create_file_fan(new_client, 1);
|
||||
device_create_file_fan(new_client, 2);
|
||||
device_create_file_fan(new_client, 3);
|
||||
|
||||
device_create_file_temp(new_client, 1);
|
||||
device_create_file_temp(new_client, 2);
|
||||
device_create_file_temp(new_client, 3);
|
||||
|
||||
return 0;
|
||||
|
||||
exit_remove_files:
|
||||
sysfs_remove_group(&new_client->dev.kobj, &fscher_group);
|
||||
exit_detach:
|
||||
i2c_detach_client(new_client);
|
||||
exit_free:
|
||||
@@ -381,6 +368,7 @@ static int fscher_detach_client(struct i2c_client *client)
|
||||
int err;
|
||||
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
sysfs_remove_group(&client->dev.kobj, &fscher_group);
|
||||
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
|
||||
+46
-29
@@ -38,6 +38,7 @@
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
|
||||
/*
|
||||
* Addresses to scan
|
||||
@@ -432,6 +433,44 @@ static DEVICE_ATTR(in0_input, S_IRUGO, show_volt_12, NULL);
|
||||
static DEVICE_ATTR(in1_input, S_IRUGO, show_volt_5, NULL);
|
||||
static DEVICE_ATTR(in2_input, S_IRUGO, show_volt_batt, NULL);
|
||||
|
||||
static struct attribute *fscpos_attributes[] = {
|
||||
&dev_attr_event.attr,
|
||||
&dev_attr_in0_input.attr,
|
||||
&dev_attr_in1_input.attr,
|
||||
&dev_attr_in2_input.attr,
|
||||
|
||||
&dev_attr_wdog_control.attr,
|
||||
&dev_attr_wdog_preset.attr,
|
||||
&dev_attr_wdog_state.attr,
|
||||
|
||||
&dev_attr_temp1_input.attr,
|
||||
&dev_attr_temp1_status.attr,
|
||||
&dev_attr_temp1_reset.attr,
|
||||
&dev_attr_temp2_input.attr,
|
||||
&dev_attr_temp2_status.attr,
|
||||
&dev_attr_temp2_reset.attr,
|
||||
&dev_attr_temp3_input.attr,
|
||||
&dev_attr_temp3_status.attr,
|
||||
&dev_attr_temp3_reset.attr,
|
||||
|
||||
&dev_attr_fan1_input.attr,
|
||||
&dev_attr_fan1_status.attr,
|
||||
&dev_attr_fan1_ripple.attr,
|
||||
&dev_attr_pwm1.attr,
|
||||
&dev_attr_fan2_input.attr,
|
||||
&dev_attr_fan2_status.attr,
|
||||
&dev_attr_fan2_ripple.attr,
|
||||
&dev_attr_pwm2.attr,
|
||||
&dev_attr_fan3_input.attr,
|
||||
&dev_attr_fan3_status.attr,
|
||||
&dev_attr_fan3_ripple.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group fscpos_group = {
|
||||
.attrs = fscpos_attributes,
|
||||
};
|
||||
|
||||
static int fscpos_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
@@ -497,42 +536,19 @@ static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
dev_info(&new_client->dev, "Found fscpos chip, rev %u\n", data->revision);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
if ((err = sysfs_create_group(&new_client->dev.kobj, &fscpos_group)))
|
||||
goto exit_detach;
|
||||
|
||||
data->class_dev = hwmon_device_register(&new_client->dev);
|
||||
if (IS_ERR(data->class_dev)) {
|
||||
err = PTR_ERR(data->class_dev);
|
||||
goto exit_detach;
|
||||
goto exit_remove_files;
|
||||
}
|
||||
|
||||
device_create_file(&new_client->dev, &dev_attr_event);
|
||||
device_create_file(&new_client->dev, &dev_attr_in0_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_in1_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_in2_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_wdog_control);
|
||||
device_create_file(&new_client->dev, &dev_attr_wdog_preset);
|
||||
device_create_file(&new_client->dev, &dev_attr_wdog_state);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_status);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp1_reset);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp2_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp2_status);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp2_reset);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp3_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp3_status);
|
||||
device_create_file(&new_client->dev, &dev_attr_temp3_reset);
|
||||
device_create_file(&new_client->dev, &dev_attr_fan1_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_fan1_status);
|
||||
device_create_file(&new_client->dev, &dev_attr_fan1_ripple);
|
||||
device_create_file(&new_client->dev, &dev_attr_pwm1);
|
||||
device_create_file(&new_client->dev, &dev_attr_fan2_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_fan2_status);
|
||||
device_create_file(&new_client->dev, &dev_attr_fan2_ripple);
|
||||
device_create_file(&new_client->dev, &dev_attr_pwm2);
|
||||
device_create_file(&new_client->dev, &dev_attr_fan3_input);
|
||||
device_create_file(&new_client->dev, &dev_attr_fan3_status);
|
||||
device_create_file(&new_client->dev, &dev_attr_fan3_ripple);
|
||||
|
||||
return 0;
|
||||
|
||||
exit_remove_files:
|
||||
sysfs_remove_group(&new_client->dev.kobj, &fscpos_group);
|
||||
exit_detach:
|
||||
i2c_detach_client(new_client);
|
||||
exit_free:
|
||||
@@ -547,6 +563,7 @@ static int fscpos_detach_client(struct i2c_client *client)
|
||||
int err;
|
||||
|
||||
hwmon_device_unregister(data->class_dev);
|
||||
sysfs_remove_group(&client->dev.kobj, &fscpos_group);
|
||||
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user