Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
b4669d66
Commit
b4669d66
authored
Feb 07, 2006
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/i2c-2.6
parents
b43d4dda
c5e3fbf2
Changes
20
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
1111 additions
and
40 deletions
+1111
-40
Documentation/feature-removal-schedule.txt
Documentation/feature-removal-schedule.txt
+9
-0
Documentation/hwmon/f71805f
Documentation/hwmon/f71805f
+105
-0
Documentation/hwmon/it87
Documentation/hwmon/it87
+1
-1
Documentation/hwmon/sysfs-interface
Documentation/hwmon/sysfs-interface
+17
-1
Documentation/i2c/busses/i2c-sis96x
Documentation/i2c/busses/i2c-sis96x
+2
-2
MAINTAINERS
MAINTAINERS
+6
-0
drivers/hwmon/Kconfig
drivers/hwmon/Kconfig
+10
-0
drivers/hwmon/Makefile
drivers/hwmon/Makefile
+1
-0
drivers/hwmon/f71805f.c
drivers/hwmon/f71805f.c
+908
-0
drivers/hwmon/it87.c
drivers/hwmon/it87.c
+6
-2
drivers/hwmon/lm77.c
drivers/hwmon/lm77.c
+4
-4
drivers/hwmon/w83792d.c
drivers/hwmon/w83792d.c
+14
-17
drivers/i2c/algos/i2c-algo-sibyte.c
drivers/i2c/algos/i2c-algo-sibyte.c
+1
-1
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Kconfig
+1
-0
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-i801.c
+2
-0
drivers/i2c/busses/i2c-parport-light.c
drivers/i2c/busses/i2c-parport-light.c
+3
-6
drivers/i2c/busses/i2c-parport.c
drivers/i2c/busses/i2c-parport.c
+2
-5
drivers/i2c/busses/i2c-pxa.c
drivers/i2c/busses/i2c-pxa.c
+1
-1
drivers/i2c/i2c-core.c
drivers/i2c/i2c-core.c
+15
-0
include/linux/i2c.h
include/linux/i2c.h
+3
-0
No files found.
Documentation/feature-removal-schedule.txt
View file @
b4669d66
...
@@ -162,3 +162,12 @@ What: pci_module_init(driver)
...
@@ -162,3 +162,12 @@ What: pci_module_init(driver)
When: January 2007
When: January 2007
Why: Is replaced by pci_register_driver(pci_driver).
Why: Is replaced by pci_register_driver(pci_driver).
Who: Richard Knutsson <ricknu-0@student.ltu.se> and Greg Kroah-Hartman <gregkh@suse.de>
Who: Richard Knutsson <ricknu-0@student.ltu.se> and Greg Kroah-Hartman <gregkh@suse.de>
---------------------------
What: I2C interface of the it87 driver
When: January 2007
Why: The ISA interface is faster and should be always available. The I2C
probing is also known to cause trouble in at least one case (see
bug #5889.)
Who: Jean Delvare <khali@linux-fr.org>
Documentation/hwmon/f71805f
0 → 100644
View file @
b4669d66
Kernel driver f71805f
=====================
Supported chips:
* Fintek F71805F/FG
Prefix: 'f71805f'
Addresses scanned: none, address read from Super I/O config space
Datasheet: Provided by Fintek on request
Author: Jean Delvare <khali@linux-fr.org>
Thanks to Denis Kieft from Barracuda Networks for the donation of a
test system (custom Jetway K8M8MS motherboard, with CPU and RAM) and
for providing initial documentation.
Thanks to Kris Chen from Fintek for answering technical questions and
providing additional documentation.
Thanks to Chris Lin from Jetway for providing wiring schematics and
anwsering technical questions.
Description
-----------
The Fintek F71805F/FG Super I/O chip includes complete hardware monitoring
capabilities. It can monitor up to 9 voltages (counting its own power
source), 3 fans and 3 temperature sensors.
This chip also has fan controlling features, using either DC or PWM, in
three different modes (one manual, two automatic). The driver doesn't
support these features yet.
The driver assumes that no more than one chip is present, which seems
reasonable.
Voltage Monitoring
------------------
Voltages are sampled by an 8-bit ADC with a LSB of 8 mV. The supported
range is thus from 0 to 2.040 V. Voltage values outside of this range
need external resistors. An exception is in0, which is used to monitor
the chip's own power source (+3.3V), and is divided internally by a
factor 2.
The two LSB of the voltage limit registers are not used (always 0), so
you can only set the limits in steps of 32 mV (before scaling).
The wirings and resistor values suggested by Fintek are as follow:
pin expected
name use R1 R2 divider raw val.
in0 VCC VCC3.3V int. int. 2.00 1.65 V
in1 VIN1 VTT1.2V 10K - 1.00 1.20 V
in2 VIN2 VRAM 100K 100K 2.00 ~1.25 V (1)
in3 VIN3 VCHIPSET 47K 100K 1.47 2.24 V (2)
in4 VIN4 VCC5V 200K 47K 5.25 0.95 V
in5 VIN5 +12V 200K 20K 11.00 1.05 V
in6 VIN6 VCC1.5V 10K - 1.00 1.50 V
in7 VIN7 VCORE 10K - 1.00 ~1.40 V (1)
in8 VIN8 VSB5V 200K 47K 1.00 0.95 V
(1) Depends on your hardware setup.
(2) Obviously not correct, swapping R1 and R2 would make more sense.
These values can be used as hints at best, as motherboard manufacturers
are free to use a completely different setup. As a matter of fact, the
Jetway K8M8MS uses a significantly different setup. You will have to
find out documentation about your own motherboard, and edit sensors.conf
accordingly.
Each voltage measured has associated low and high limits, each of which
triggers an alarm when crossed.
Fan Monitoring
--------------
Fan rotation speeds are reported as 12-bit values from a gated clock
signal. Speeds down to 366 RPM can be measured. There is no theoretical
high limit, but values over 6000 RPM seem to cause problem. The effective
resolution is much lower than you would expect, the step between different
register values being 10 rather than 1.
The chip assumes 2 pulse-per-revolution fans.
An alarm is triggered if the rotation speed drops below a programmable
limit or is too low to be measured.
Temperature Monitoring
----------------------
Temperatures are reported in degrees Celsius. Each temperature measured
has a high limit, those crossing triggers an alarm. There is an associated
hysteresis value, below which the temperature has to drop before the
alarm is cleared.
All temperature channels are external, there is no embedded temperature
sensor. Each channel can be used for connecting either a thermal diode
or a thermistor. The driver reports the currently selected mode, but
doesn't allow changing it. In theory, the BIOS should have configured
everything properly.
Documentation/hwmon/it87
View file @
b4669d66
...
@@ -9,7 +9,7 @@ Supported chips:
...
@@ -9,7 +9,7 @@ Supported chips:
http://www.ite.com.tw/
http://www.ite.com.tw/
* IT8712F
* IT8712F
Prefix: 'it8712'
Prefix: 'it8712'
Addresses scanned: I2C 0x2
8 - 0x2f
Addresses scanned: I2C 0x2
d
from Super I/O config space (8 I/O ports)
from Super I/O config space (8 I/O ports)
Datasheet: Publicly available at the ITE website
Datasheet: Publicly available at the ITE website
http://www.ite.com.tw/
http://www.ite.com.tw/
...
...
Documentation/hwmon/sysfs-interface
View file @
b4669d66
...
@@ -179,11 +179,12 @@ temp[1-*]_auto_point[1-*]_temp_hyst
...
@@ -179,11 +179,12 @@ temp[1-*]_auto_point[1-*]_temp_hyst
****************
****************
temp[1-3]_type Sensor type selection.
temp[1-3]_type Sensor type selection.
Integers 1
, 2, 3 or thermistor Beta value (
3435)
Integers 1
to 4 or thermistor Beta value (typically
3435)
Read/Write.
Read/Write.
1: PII/Celeron Diode
1: PII/Celeron Diode
2: 3904 transistor
2: 3904 transistor
3: thermal diode
3: thermal diode
4: thermistor (default/unknown Beta)
Not all types are supported by all chips
Not all types are supported by all chips
temp[1-4]_max Temperature max value.
temp[1-4]_max Temperature max value.
...
@@ -261,6 +262,21 @@ alarms Alarm bitmask.
...
@@ -261,6 +262,21 @@ alarms Alarm bitmask.
of individual bits.
of individual bits.
Bits are defined in kernel/include/sensors.h.
Bits are defined in kernel/include/sensors.h.
alarms_in Alarm bitmask relative to in (voltage) channels
Read only
A '1' bit means an alarm, LSB corresponds to in0 and so on
Prefered to 'alarms' for newer chips
alarms_fan Alarm bitmask relative to fan channels
Read only
A '1' bit means an alarm, LSB corresponds to fan1 and so on
Prefered to 'alarms' for newer chips
alarms_temp Alarm bitmask relative to temp (temperature) channels
Read only
A '1' bit means an alarm, LSB corresponds to temp1 and so on
Prefered to 'alarms' for newer chips
beep_enable Beep/interrupt enable
beep_enable Beep/interrupt enable
0 to disable.
0 to disable.
1 to enable.
1 to enable.
...
...
Documentation/i2c/busses/i2c-sis
69
x
→
Documentation/i2c/busses/i2c-sis
96
x
View file @
b4669d66
...
@@ -7,7 +7,7 @@ Supported adapters:
...
@@ -7,7 +7,7 @@ Supported adapters:
Any combination of these host bridges:
Any combination of these host bridges:
645, 645DX (aka 646), 648, 650, 651, 655, 735, 745, 746
645, 645DX (aka 646), 648, 650, 651, 655, 735, 745, 746
and these south bridges:
and these south bridges:
961, 962, 963(L)
961, 962, 963(L)
Author: Mark M. Hoffman <mhoffman@lightlink.com>
Author: Mark M. Hoffman <mhoffman@lightlink.com>
...
@@ -29,7 +29,7 @@ The command "lspci" as root should produce something like these lines:
...
@@ -29,7 +29,7 @@ The command "lspci" as root should produce something like these lines:
or perhaps this...
or perhaps this...
00:00.0 Host bridge: Silicon Integrated Systems [SiS]: Unknown device 0645
00:00.0 Host bridge: Silicon Integrated Systems [SiS]: Unknown device 0645
00:02.0 ISA bridge: Silicon Integrated Systems [SiS]: Unknown device 0961
00:02.0 ISA bridge: Silicon Integrated Systems [SiS]: Unknown device 0961
00:02.1 SMBus: Silicon Integrated Systems [SiS]: Unknown device 0016
00:02.1 SMBus: Silicon Integrated Systems [SiS]: Unknown device 0016
...
...
MAINTAINERS
View file @
b4669d66
...
@@ -931,6 +931,12 @@ M: sct@redhat.com, akpm@osdl.org, adilger@clusterfs.com
...
@@ -931,6 +931,12 @@ M: sct@redhat.com, akpm@osdl.org, adilger@clusterfs.com
L: ext3-users@redhat.com
L: ext3-users@redhat.com
S: Maintained
S: Maintained
F71805F HARDWARE MONITORING DRIVER
P: Jean Delvare
M: khali@linux-fr.org
L: lm-sensors@lm-sensors.org
S: Maintained
FARSYNC SYNCHRONOUS DRIVER
FARSYNC SYNCHRONOUS DRIVER
P: Kevin Curtis
P: Kevin Curtis
M: kevin.curtis@farsite.co.uk
M: kevin.curtis@farsite.co.uk
...
...
drivers/hwmon/Kconfig
View file @
b4669d66
...
@@ -113,6 +113,16 @@ config SENSORS_DS1621
...
@@ -113,6 +113,16 @@ config SENSORS_DS1621
This driver can also be built as a module. If so, the module
This driver can also be built as a module. If so, the module
will be called ds1621.
will be called ds1621.
config SENSORS_F71805F
tristate "Fintek F71805F/FG"
depends on HWMON && EXPERIMENTAL
help
If you say yes here you get support for hardware monitoring
features of the Fintek F71805F/FG chips.
This driver can also be built as a module. If so, the module
will be called f71805f.
config SENSORS_FSCHER
config SENSORS_FSCHER
tristate "FSC Hermes"
tristate "FSC Hermes"
depends on HWMON && I2C && EXPERIMENTAL
depends on HWMON && I2C && EXPERIMENTAL
...
...
drivers/hwmon/Makefile
View file @
b4669d66
...
@@ -18,6 +18,7 @@ obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o
...
@@ -18,6 +18,7 @@ obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o
obj-$(CONFIG_SENSORS_ADM9240)
+=
adm9240.o
obj-$(CONFIG_SENSORS_ADM9240)
+=
adm9240.o
obj-$(CONFIG_SENSORS_ATXP1)
+=
atxp1.o
obj-$(CONFIG_SENSORS_ATXP1)
+=
atxp1.o
obj-$(CONFIG_SENSORS_DS1621)
+=
ds1621.o
obj-$(CONFIG_SENSORS_DS1621)
+=
ds1621.o
obj-$(CONFIG_SENSORS_F71805F)
+=
f71805f.o
obj-$(CONFIG_SENSORS_FSCHER)
+=
fscher.o
obj-$(CONFIG_SENSORS_FSCHER)
+=
fscher.o
obj-$(CONFIG_SENSORS_FSCPOS)
+=
fscpos.o
obj-$(CONFIG_SENSORS_FSCPOS)
+=
fscpos.o
obj-$(CONFIG_SENSORS_GL518SM)
+=
gl518sm.o
obj-$(CONFIG_SENSORS_GL518SM)
+=
gl518sm.o
...
...
drivers/hwmon/f71805f.c
0 → 100644
View file @
b4669d66
/*
* 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>
*
* The F71805F/FG is a LPC Super-I/O chip made by Fintek. It integrates
* complete hardware monitoring features: voltage, fan and temperature
* sensors, and manual and automatic fan speed control.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/platform_device.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <asm/io.h>
static
struct
platform_device
*
pdev
;
#define DRVNAME "f71805f"
/*
* Super-I/O constants and functions
*/
#define F71805F_LD_HWM 0x04
#define SIO_REG_LDSEL 0x07
/* Logical device select */
#define SIO_REG_DEVID 0x20
/* Device ID (2 bytes) */
#define SIO_REG_DEVREV 0x22
/* Device revision */
#define SIO_REG_MANID 0x23
/* Fintek ID (2 bytes) */
#define SIO_REG_ENABLE 0x30
/* Logical device enable */
#define SIO_REG_ADDR 0x60
/* Logical device address (2 bytes) */
#define SIO_FINTEK_ID 0x1934
#define SIO_F71805F_ID 0x0406
static
inline
int
superio_inb
(
int
base
,
int
reg
)
{
outb
(
reg
,
base
);
return
inb
(
base
+
1
);
}
static
int
superio_inw
(
int
base
,
int
reg
)
{
int
val
;
outb
(
reg
++
,
base
);
val
=
inb
(
base
+
1
)
<<
8
;
outb
(
reg
,
base
);
val
|=
inb
(
base
+
1
);
return
val
;
}
static
inline
void
superio_select
(
int
base
,
int
ld
)
{
outb
(
SIO_REG_LDSEL
,
base
);
outb
(
ld
,
base
+
1
);
}
static
inline
void
superio_enter
(
int
base
)
{
outb
(
0x87
,
base
);
outb
(
0x87
,
base
);
}
static
inline
void
superio_exit
(
int
base
)
{
outb
(
0xaa
,
base
);
}
/*
* ISA constants
*/
#define REGION_LENGTH 2
#define ADDR_REG_OFFSET 0
#define DATA_REG_OFFSET 1
static
struct
resource
f71805f_resource
__initdata
=
{
.
flags
=
IORESOURCE_IO
,
};
/*
* Registers
*/
/* in nr from 0 to 8 (8-bit values) */
#define F71805F_REG_IN(nr) (0x10 + (nr))
#define F71805F_REG_IN_HIGH(nr) (0x40 + 2 * (nr))
#define F71805F_REG_IN_LOW(nr) (0x41 + 2 * (nr))
/* fan nr from 0 to 2 (12-bit values, two registers) */
#define F71805F_REG_FAN(nr) (0x20 + 2 * (nr))
#define F71805F_REG_FAN_LOW(nr) (0x28 + 2 * (nr))
#define F71805F_REG_FAN_CTRL(nr) (0x60 + 16 * (nr))
/* temp nr from 0 to 2 (8-bit values) */
#define F71805F_REG_TEMP(nr) (0x1B + (nr))
#define F71805F_REG_TEMP_HIGH(nr) (0x54 + 2 * (nr))
#define F71805F_REG_TEMP_HYST(nr) (0x55 + 2 * (nr))
#define F71805F_REG_TEMP_MODE 0x01
#define F71805F_REG_START 0x00
/* status nr from 0 to 2 */
#define F71805F_REG_STATUS(nr) (0x36 + (nr))
/*
* Data structures and manipulation thereof
*/
struct
f71805f_data
{
unsigned
short
addr
;
const
char
*
name
;
struct
semaphore
lock
;
struct
class_device
*
class_dev
;
struct
semaphore
update_lock
;
char
valid
;
/* !=0 if following fields are valid */
unsigned
long
last_updated
;
/* In jiffies */
unsigned
long
last_limits
;
/* In jiffies */
/* Register values */
u8
in
[
9
];
u8
in_high
[
9
];
u8
in_low
[
9
];
u16
fan
[
3
];
u16
fan_low
[
3
];
u8
fan_enabled
;
/* Read once at init time */
u8
temp
[
3
];
u8
temp_high
[
3
];
u8
temp_hyst
[
3
];
u8
temp_mode
;
u8
alarms
[
3
];
};
static
inline
long
in_from_reg
(
u8
reg
)
{
return
(
reg
*
8
);
}
/* The 2 least significant bits are not used */
static
inline
u8
in_to_reg
(
long
val
)
{
if
(
val
<=
0
)
return
0
;
if
(
val
>=
2016
)
return
0xfc
;
return
(((
val
+
16
)
/
32
)
<<
2
);
}
/* in0 is downscaled by a factor 2 internally */
static
inline
long
in0_from_reg
(
u8
reg
)
{
return
(
reg
*
16
);
}
static
inline
u8
in0_to_reg
(
long
val
)
{
if
(
val
<=
0
)
return
0
;
if
(
val
>=
4032
)
return
0xfc
;
return
(((
val
+
32
)
/
64
)
<<
2
);
}
/* The 4 most significant bits are not used */
static
inline
long
fan_from_reg
(
u16
reg
)
{
reg
&=
0xfff
;
if
(
!
reg
||
reg
==
0xfff
)
return
0
;
return
(
1500000
/
reg
);
}
static
inline
u16
fan_to_reg
(
long
rpm
)
{
/* If the low limit is set below what the chip can measure,
store the largest possible 12-bit value in the registers,
so that no alarm will ever trigger. */
if
(
rpm
<
367
)
return
0xfff
;
return
(
1500000
/
rpm
);
}
static
inline
long
temp_from_reg
(
u8
reg
)
{
return
(
reg
*
1000
);
}
static
inline
u8
temp_to_reg
(
long
val
)
{
if
(
val
<
0
)
val
=
0
;
else
if
(
val
>
1000
*
0xff
)
val
=
0xff
;
return
((
val
+
500
)
/
1000
);
}
/*
* Device I/O access
*/
static
u8
f71805f_read8
(
struct
f71805f_data
*
data
,
u8
reg
)
{
u8
val
;
down
(
&
data
->
lock
);
outb
(
reg
,
data
->
addr
+
ADDR_REG_OFFSET
);
val
=
inb
(
data
->
addr
+
DATA_REG_OFFSET
);
up
(
&
data
->
lock
);
return
val
;
}
static
void
f71805f_write8
(
struct
f71805f_data
*
data
,
u8
reg
,
u8
val
)
{
down
(
&
data
->
lock
);
outb
(
reg
,
data
->
addr
+
ADDR_REG_OFFSET
);
outb
(
val
,
data
->
addr
+
DATA_REG_OFFSET
);
up
(
&
data
->
lock
);
}
/* It is important to read the MSB first, because doing so latches the
value of the LSB, so we are sure both bytes belong to the same value. */
static
u16
f71805f_read16
(
struct
f71805f_data
*
data
,
u8
reg
)
{
u16
val
;
down
(
&
data
->
lock
);
outb
(
reg
,
data
->
addr
+
ADDR_REG_OFFSET
);
val
=
inb
(
data
->
addr
+
DATA_REG_OFFSET
)
<<
8
;
outb
(
++
reg
,
data
->
addr
+
ADDR_REG_OFFSET
);
val
|=
inb
(
data
->
addr
+
DATA_REG_OFFSET
);
up
(
&
data
->
lock
);
return
val
;
}
static
void
f71805f_write16
(
struct
f71805f_data
*
data
,
u8
reg
,
u16
val
)
{
down
(
&
data
->
lock
);
outb
(
reg
,
data
->
addr
+
ADDR_REG_OFFSET
);
outb
(
val
>>
8
,
data
->
addr
+
DATA_REG_OFFSET
);
outb
(
++
reg
,
data
->
addr
+
ADDR_REG_OFFSET
);
outb
(
val
&
0xff
,
data
->
addr
+
DATA_REG_OFFSET
);
up
(
&
data
->
lock
);
}
static
struct
f71805f_data
*
f71805f_update_device
(
struct
device
*
dev
)
{
struct
f71805f_data
*
data
=
dev_get_drvdata
(
dev
);
int
nr
;
down
(
&
data
->
update_lock
);
/* Limit registers cache is refreshed after 60 seconds */
if
(
time_after
(
jiffies
,
data
->
last_updated
+
60
*
HZ
)
||
!
data
->
valid
)
{
for
(
nr
=
0
;
nr
<
9
;
nr
++
)
{
data
->
in_high
[
nr
]
=
f71805f_read8
(
data
,
F71805F_REG_IN_HIGH
(
nr
));
data
->
in_low
[
nr
]
=
f71805f_read8
(
data
,
F71805F_REG_IN_LOW
(
nr
));
}
for
(
nr
=
0
;
nr
<
3
;
nr
++
)
{
if
(
data
->
fan_enabled
&
(
1
<<
nr
))
data
->
fan_low
[
nr
]
=
f71805f_read16
(
data
,
F71805F_REG_FAN_LOW
(
nr
));
}
for
(
nr
=
0
;
nr
<
3
;
nr
++
)
{
data
->
temp_high
[
nr
]
=
f71805f_read8
(
data
,
F71805F_REG_TEMP_HIGH
(
nr
));
data
->
temp_hyst
[
nr
]
=
f71805f_read8
(
data
,
F71805F_REG_TEMP_HYST
(
nr
));
}
data
->
temp_mode
=
f71805f_read8
(
data
,
F71805F_REG_TEMP_MODE
);
data
->
last_limits
=
jiffies
;
}
/* Measurement registers cache is refreshed after 1 second */
if
(
time_after
(
jiffies
,
data
->
last_updated
+
HZ
)
||
!
data
->
valid
)
{
for
(
nr
=
0
;
nr
<
9
;
nr
++
)
{
data
->
in
[
nr
]
=
f71805f_read8
(
data
,
F71805F_REG_IN
(
nr
));
}
for
(
nr
=
0
;
nr
<
3
;
nr
++
)
{
if
(
data
->
fan_enabled
&
(
1
<<
nr
))
data
->
fan
[
nr
]
=
f71805f_read16
(
data
,
F71805F_REG_FAN
(
nr
));
}
for
(
nr
=
0
;
nr
<
3
;
nr
++
)
{
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
->
last_updated
=
jiffies
;
data
->
valid
=
1
;
}
up
(
&
data
->
update_lock
);
return
data
;
}
/*
* Sysfs interface
*/
static
ssize_t
show_in0
(
struct
device
*
dev
,
struct
device_attribute
*
devattr
,
char
*
buf
)
{
struct
f71805f_data
*
data
=
f71805f_update_device
(
dev
);
return
sprintf
(
buf
,
"%ld
\n
"
,
in0_from_reg
(
data
->
in
[
0
]));
}
static
ssize_t
show_in0_max
(
struct
device
*
dev
,
struct
device_attribute
*
devattr
,
char
*
buf
)
{
struct
f71805f_data
*
data
=
f71805f_update_device
(
dev
);
return
sprintf
(
buf
,
"%ld
\n
"
,
in0_from_reg
(
data
->
in_high
[
0
]));
}
static
ssize_t
show_in0_min
(
struct
device
*
dev
,
struct
device_attribute
*
devattr
,
char
*
buf
)
{
struct
f71805f_data
*
data
=
f71805f_update_device
(
dev
);
return
sprintf
(
buf
,
"%ld
\n
"
,
in0_from_reg
(
data
->
in_low
[
0
]));
}
static
ssize_t
set_in0_max
(
struct
device
*
dev
,
struct
device_attribute
*
devattr
,
const
char
*
buf
,
size_t
count
)
{
struct
f71805f_data
*
data
=
dev_get_drvdata
(
dev
);
long
val
=
simple_strtol
(
buf
,
NULL
,
10
);
down
(
&
data
->
update_lock
);
data
->
in_high
[
0
]
=
in0_to_reg
(
val
);
f71805f_write8
(
data
,
F71805F_REG_IN_HIGH
(
0
),
data
->
in_high
[
0
]);
up
(
&
data
->
update_lock
);
return
count
;
}
static
ssize_t
set_in0_min
(
struct
device
*
dev
,
struct
device_attribute
*
devattr
,
const
char
*
buf
,
size_t
count
)
{
struct
f71805f_data
*
data
=
dev_get_drvdata
(
dev
);
long
val
=
simple_strtol
(
buf
,
NULL
,
10
);
down
(
&
data
->
update_lock
);
data
->
in_low
[
0
]
=
in0_to_reg
(
val
);
f71805f_write8
(
data
,
F71805F_REG_IN_LOW
(
0
),
data
->
in_low
[
0
]);
up
(
&
data
->
update_lock
);
return
count
;
}
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
ssize_t
show_in
(
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
nr
=
attr
->
index
;
return
sprintf
(
buf
,
"%ld
\n
"
,
in_from_reg
(
data
->
in
[
nr
]));
}
static
ssize_t
show_in_max
(
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
nr
=
attr
->
index
;
return
sprintf
(
buf
,
"%ld
\n
"
,
in_from_reg
(
data
->
in_high
[
nr
]));
}
static
ssize_t
show_in_min
(
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
nr
=
attr
->
index
;
return
sprintf
(
buf
,
"%ld
\n
"
,
in_from_reg
(
data
->
in_low
[
nr
]));
}
static
ssize_t
set_in_max
(
struct
device
*
dev
,
struct
device_attribute
*
devattr
,
const
char
*
buf
,
size_t
count
)
{
struct
f71805f_data
*
data
=
dev_get_drvdata
(
dev
);
struct
sensor_device_attribute
*
attr
=
to_sensor_dev_attr
(
devattr
);
int
nr
=
attr
->
index
;
long
val
=
simple_strtol
(
buf
,
NULL
,
10
);
down
(
&
data
->
update_lock
);
data
->
in_high
[
nr
]
=
in_to_reg
(
val
);
f71805f_write8
(
data
,
F71805F_REG_IN_HIGH
(
nr
),
data
->
in_high
[
nr
]);
up
(
&
data
->
update_lock
);
return
count
;
}
static
ssize_t
set_in_min
(
struct
device
*
dev
,
struct
device_attribute
*
devattr
,
const
char
*
buf
,
size_t
count
)
{
struct
f71805f_data
*
data
=
dev_get_drvdata
(
dev
);
struct
sensor_device_attribute
*
attr
=
to_sensor_dev_attr
(
devattr
);
int
nr
=
attr
->
index
;
long
val
=
simple_strtol
(
buf
,
NULL
,
10
);
down
(
&
data
->
update_lock
);
data
->
in_low
[
nr
]
=
in_to_reg
(
val
);
f71805f_write8
(
data
,
F71805F_REG_IN_LOW
(
nr
),
data
->
in_low
[
nr
]);
up
(
&
data
->
update_lock
);
return
count
;
}
#define sysfs_in(offset) \
static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \
show_in, NULL, offset); \
static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
show_in_max, set_in_max, offset); \
static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
show_in_min, set_in_min, offset)
sysfs_in
(
1
);
sysfs_in
(
2
);
sysfs_in
(
3
);
sysfs_in
(
4
);
sysfs_in
(
5
);
sysfs_in
(
6
);
sysfs_in
(
7
);
sysfs_in
(
8
);
static
ssize_t
show_fan
(
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
nr
=
attr
->
index
;
return
sprintf
(
buf
,
"%ld
\n
"
,
fan_from_reg
(
data
->
fan
[
nr
]));
}
static
ssize_t
show_fan_min
(
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
nr
=
attr
->
index
;
return
sprintf
(
buf
,
"%ld
\n
"
,
fan_from_reg
(
data
->
fan_low
[
nr
]));
}
static
ssize_t
set_fan_min
(
struct
device
*
dev
,
struct
device_attribute
*
devattr
,
const
char
*
buf
,
size_t
count
)
{
struct
f71805f_data
*
data
=
dev_get_drvdata
(
dev
);
struct
sensor_device_attribute
*
attr
=
to_sensor_dev_attr
(
devattr
);
int
nr
=
attr
->
index
;
long
val
=
simple_strtol
(
buf
,
NULL
,
10
);
down
(
&
data
->
update_lock
);
data
->
fan_low
[
nr
]
=
fan_to_reg
(
val
);
f71805f_write16
(
data
,
F71805F_REG_FAN_LOW
(
nr
),
data
->
fan_low
[
nr
]);
up
(
&
data
->
update_lock
);
return
count
;
}
#define sysfs_fan(offset) \
static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
show_fan, NULL, offset - 1); \
static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
show_fan_min, set_fan_min, offset - 1)
sysfs_fan
(
1
);
sysfs_fan
(
2
);
sysfs_fan
(
3
);
static
ssize_t
show_temp
(
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
nr
=
attr
->
index
;
return
sprintf
(
buf
,
"%ld
\n
"
,
temp_from_reg
(
data
->
temp
[
nr
]));
}
static
ssize_t
show_temp_max
(
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
nr
=
attr
->
index
;
return
sprintf
(
buf
,
"%ld
\n
"
,
temp_from_reg
(
data
->
temp_high
[
nr
]));
}
static
ssize_t
show_temp_hyst
(
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
nr
=
attr
->
index
;
return
sprintf
(
buf
,
"%ld
\n
"
,
temp_from_reg
(
data
->
temp_hyst
[
nr
]));
}
static
ssize_t
show_temp_type
(
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
nr
=
attr
->
index
;
/* 3 is diode, 4 is thermistor */
return
sprintf
(
buf
,
"%u
\n
"
,
(
data
->
temp_mode
&
(
1
<<
nr
))
?
3
:
4
);
}
static
ssize_t
set_temp_max
(
struct
device
*
dev
,
struct
device_attribute
*
devattr
,
const
char
*
buf
,
size_t
count
)
{
struct
f71805f_data
*
data
=
dev_get_drvdata
(
dev
);
struct
sensor_device_attribute
*
attr
=
to_sensor_dev_attr
(
devattr
);
int
nr
=
attr
->
index
;
long
val
=
simple_strtol
(
buf
,
NULL
,
10
);
down
(
&
data
->
update_lock
);
data
->
temp_high
[
nr
]
=
temp_to_reg
(
val
);
f71805f_write8
(
data
,
F71805F_REG_TEMP_HIGH
(
nr
),
data
->
temp_high
[
nr
]);
up
(
&
data
->
update_lock
);
return
count
;
}
static
ssize_t
set_temp_hyst
(
struct
device
*
dev
,
struct
device_attribute
*
devattr
,
const
char
*
buf
,
size_t
count
)
{
struct
f71805f_data
*
data
=
dev_get_drvdata
(
dev
);
struct
sensor_device_attribute
*
attr
=
to_sensor_dev_attr
(
devattr
);
int
nr
=
attr
->
index
;
long
val
=
simple_strtol
(
buf
,
NULL
,
10
);
down
(
&
data
->
update_lock
);
data
->
temp_hyst
[
nr
]
=
temp_to_reg
(
val
);
f71805f_write8
(
data
,
F71805F_REG_TEMP_HYST
(
nr
),
data
->
temp_hyst
[
nr
]);
up
(
&
data
->
update_lock
);
return
count
;
}
#define sysfs_temp(offset) \
static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
show_temp, NULL, offset - 1); \
static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \
show_temp_max, set_temp_max, offset - 1); \
static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \
show_temp_hyst, set_temp_hyst, offset - 1); \
static SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO, \
show_temp_type, NULL, offset - 1)
sysfs_temp
(
1
);
sysfs_temp
(
2
);
sysfs_temp
(
3
);
static
ssize_t
show_alarms_in
(
struct
device
*
dev
,
struct
device_attribute
*
devattr
,
char
*
buf
)
{
struct
f71805f_data
*
data
=
f71805f_update_device
(
dev
);
return
sprintf
(
buf
,
"%d
\n
"
,
data
->
alarms
[
0
]
|
((
data
->
alarms
[
1
]
&
0x01
)
<<
8
));
}
static
ssize_t
show_alarms_fan
(
struct
device
*
dev
,
struct
device_attribute
*
devattr
,
char
*
buf
)
{
struct
f71805f_data
*
data
=
f71805f_update_device
(
dev
);
return
sprintf
(
buf
,
"%d
\n
"
,
data
->
alarms
[
2
]
&
0x07
);
}
static
ssize_t
show_alarms_temp
(
struct
device
*
dev
,
struct
device_attribute
*
devattr
,
char
*
buf
)
{
struct
f71805f_data
*
data
=
f71805f_update_device
(
dev
);
return
sprintf
(
buf
,
"%d
\n
"
,
(
data
->
alarms
[
1
]
>>
3
)
&
0x07
);
}
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
ssize_t
show_name
(
struct
device
*
dev
,
struct
device_attribute
*
devattr
,
char
*
buf
)
{
struct
f71805f_data
*
data
=
dev_get_drvdata
(
dev
);
return
sprintf
(
buf
,
"%s
\n
"
,
data
->
name
);
}
static
DEVICE_ATTR
(
name
,
S_IRUGO
,
show_name
,
NULL
);
/*
* Device registration and initialization
*/
static
void
__devinit
f71805f_init_device
(
struct
f71805f_data
*
data
)
{
u8
reg
;
int
i
;
reg
=
f71805f_read8
(
data
,
F71805F_REG_START
);
if
((
reg
&
0x41
)
!=
0x01
)
{
printk
(
KERN_DEBUG
DRVNAME
": Starting monitoring "
"operations
\n
"
);
f71805f_write8
(
data
,
F71805F_REG_START
,
(
reg
|
0x01
)
&
~
0x40
);
}
/* Fan monitoring can be disabled. If it is, we won't be polling
the register values, and won't create the related sysfs files. */
for
(
i
=
0
;
i
<
3
;
i
++
)
{
reg
=
f71805f_read8
(
data
,
F71805F_REG_FAN_CTRL
(
i
));
if
(
!
(
reg
&
0x80
))
data
->
fan_enabled
|=
(
1
<<
i
);
}
}
static
int
__devinit
f71805f_probe
(
struct
platform_device
*
pdev
)
{
struct
f71805f_data
*
data
;
struct
resource
*
res
;
int
err
;
if
(
!
(
data
=
kzalloc
(
sizeof
(
struct
f71805f_data
),
GFP_KERNEL
)))
{
err
=
-
ENOMEM
;
printk
(
KERN_ERR
DRVNAME
": Out of memory
\n
"
);
goto
exit
;
}
res
=
platform_get_resource
(
pdev
,
IORESOURCE_IO
,
0
);
data
->
addr
=
res
->
start
;
init_MUTEX
(
&
data
->
lock
);
data
->
name
=
"f71805f"
;
init_MUTEX
(
&
data
->
update_lock
);
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 */
device_create_file
(
&
pdev
->
dev
,
&
dev_attr_in0_input
);
device_create_file
(
&
pdev
->
dev
,
&
dev_attr_in0_max
);
device_create_file
(
&
pdev
->
dev
,
&
dev_attr_in0_min
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_in1_input
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_in2_input
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_in3_input
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_in4_input
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_in5_input
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_in6_input
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_in7_input
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_in8_input
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_in1_max
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_in2_max
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_in3_max
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_in4_max
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_in5_max
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_in6_max
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_in7_max
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_in8_max
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_in1_min
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_in2_min
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_in3_min
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_in4_min
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_in5_min
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_in6_min
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_in7_min
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_in8_min
.
dev_attr
);
if
(
data
->
fan_enabled
&
(
1
<<
0
))
{
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_fan1_input
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_fan1_min
.
dev_attr
);
}
if
(
data
->
fan_enabled
&
(
1
<<
1
))
{
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_fan2_input
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_fan2_min
.
dev_attr
);
}
if
(
data
->
fan_enabled
&
(
1
<<
2
))
{
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_fan3_input
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_fan3_min
.
dev_attr
);
}
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_temp1_input
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_temp2_input
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_temp3_input
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_temp1_max
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_temp2_max
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_temp3_max
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_temp1_max_hyst
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_temp2_max_hyst
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_temp3_max_hyst
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_temp1_type
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_temp2_type
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
sensor_dev_attr_temp3_type
.
dev_attr
);
device_create_file
(
&
pdev
->
dev
,
&
dev_attr_alarms_in
);
device_create_file
(
&
pdev
->
dev
,
&
dev_attr_alarms_fan
);
device_create_file
(
&
pdev
->
dev
,
&
dev_attr_alarms_temp
);
device_create_file
(
&
pdev
->
dev
,
&
dev_attr_name
);
return
0
;
exit_free:
kfree
(
data
);
exit:
return
err
;
}
static
int
__devexit
f71805f_remove
(
struct
platform_device
*
pdev
)
{
struct
f71805f_data
*
data
=
platform_get_drvdata
(
pdev
);
platform_set_drvdata
(
pdev
,
NULL
);
hwmon_device_unregister
(
data
->
class_dev
);
kfree
(
data
);
return
0
;
}
static
struct
platform_driver
f71805f_driver
=
{
.
driver
=
{
.
owner
=
THIS_MODULE
,
.
name
=
DRVNAME
,
},
.
probe
=
f71805f_probe
,
.
remove
=
__devexit_p
(
f71805f_remove
),
};
static
int
__init
f71805f_device_add
(
unsigned
short
address
)
{
int
err
;
pdev
=
platform_device_alloc
(
DRVNAME
,
address
);
if
(
!
pdev
)
{
err
=
-
ENOMEM
;
printk
(
KERN_ERR
DRVNAME
": Device allocation failed
\n
"
);
goto
exit
;
}
f71805f_resource
.
start
=
address
;
f71805f_resource
.
end
=
address
+
REGION_LENGTH
-
1
;
f71805f_resource
.
name
=
pdev
->
name
;
err
=
platform_device_add_resources
(
pdev
,
&
f71805f_resource
,
1
);
if
(
err
)
{
printk
(
KERN_ERR
DRVNAME
": Device resource addition failed "
"(%d)
\n
"
,
err
);
goto
exit_device_put
;
}
err
=
platform_device_add
(
pdev
);
if
(
err
)
{
printk
(
KERN_ERR
DRVNAME
": Device addition failed (%d)
\n
"
,
err
);
goto
exit_device_put
;
}
return
0
;
exit_device_put:
platform_device_put
(
pdev
);
exit:
return
err
;
}
static
int
__init
f71805f_find
(
int
sioaddr
,
unsigned
short
*
address
)
{
int
err
=
-
ENODEV
;
u16
devid
;
superio_enter
(
sioaddr
);
devid
=
superio_inw
(
sioaddr
,
SIO_REG_MANID
);
if
(
devid
!=
SIO_FINTEK_ID
)
goto
exit
;
devid
=
superio_inw
(
sioaddr
,
SIO_REG_DEVID
);
if
(
devid
!=
SIO_F71805F_ID
)
{
printk
(
KERN_INFO
DRVNAME
": Unsupported Fintek device, "
"skipping
\n
"
);
goto
exit
;
}
superio_select
(
sioaddr
,
F71805F_LD_HWM
);
if
(
!
(
superio_inb
(
sioaddr
,
SIO_REG_ENABLE
)
&
0x01
))
{
printk
(
KERN_WARNING
DRVNAME
": Device not activated, "
"skipping
\n
"
);
goto
exit
;
}
*
address
=
superio_inw
(
sioaddr
,
SIO_REG_ADDR
);
if
(
*
address
==
0
)
{
printk
(
KERN_WARNING
DRVNAME
": Base address not set, "
"skipping
\n
"
);
goto
exit
;
}
err
=
0
;
printk
(
KERN_INFO
DRVNAME
": Found F71805F chip at %#x, revision %u
\n
"
,
*
address
,
superio_inb
(
sioaddr
,
SIO_REG_DEVREV
));
exit:
superio_exit
(
sioaddr
);
return
err
;
}
static
int
__init
f71805f_init
(
void
)
{
int
err
;
unsigned
short
address
;
if
(
f71805f_find
(
0x2e
,
&
address
)
&&
f71805f_find
(
0x4e
,
&
address
))
return
-
ENODEV
;
err
=
platform_driver_register
(
&
f71805f_driver
);
if
(
err
)
goto
exit
;
/* Sets global pdev as a side effect */
err
=
f71805f_device_add
(
address
);
if
(
err
)
goto
exit_driver
;
return
0
;
exit_driver:
platform_driver_unregister
(
&
f71805f_driver
);
exit:
return
err
;
}
static
void
__exit
f71805f_exit
(
void
)
{
platform_device_unregister
(
pdev
);
platform_driver_unregister
(
&
f71805f_driver
);
}
MODULE_AUTHOR
(
"Jean Delvare <khali@linux-fr>"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_DESCRIPTION
(
"F71805F hardware monitoring driver"
);
module_init
(
f71805f_init
);
module_exit
(
f71805f_exit
);
drivers/hwmon/it87.c
View file @
b4669d66
...
@@ -45,8 +45,7 @@
...
@@ -45,8 +45,7 @@
/* Addresses to scan */
/* Addresses to scan */
static
unsigned
short
normal_i2c
[]
=
{
0x28
,
0x29
,
0x2a
,
0x2b
,
0x2c
,
0x2d
,
static
unsigned
short
normal_i2c
[]
=
{
0x2d
,
I2C_CLIENT_END
};
0x2e
,
0x2f
,
I2C_CLIENT_END
};
static
unsigned
short
isa_address
;
static
unsigned
short
isa_address
;
/* Insmod parameters */
/* Insmod parameters */
...
@@ -830,6 +829,11 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind)
...
@@ -830,6 +829,11 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind)
if
((
err
=
i2c_attach_client
(
new_client
)))
if
((
err
=
i2c_attach_client
(
new_client
)))
goto
ERROR2
;
goto
ERROR2
;
if
(
!
is_isa
)
dev_info
(
&
new_client
->
dev
,
"The I2C interface to IT87xxF "
"hardware monitoring chips is deprecated. Please "
"report if you still rely on it.
\n
"
);
/* Check PWM configuration */
/* Check PWM configuration */
enable_pwm_interface
=
it87_check_pwm
(
new_client
);
enable_pwm_interface
=
it87_check_pwm
(
new_client
);
...
...
drivers/hwmon/lm77.c
View file @
b4669d66
...
@@ -87,15 +87,15 @@ static struct i2c_driver lm77_driver = {
...
@@ -87,15 +87,15 @@ static struct i2c_driver lm77_driver = {
/* In the temperature registers, the low 3 bits are not part of the
/* In the temperature registers, the low 3 bits are not part of the
temperature values; they are the status bits. */
temperature values; they are the status bits. */
static
inline
u
16
LM77_TEMP_TO_REG
(
int
temp
)
static
inline
s
16
LM77_TEMP_TO_REG
(
int
temp
)
{
{
int
ntemp
=
SENSORS_LIMIT
(
temp
,
LM77_TEMP_MIN
,
LM77_TEMP_MAX
);
int
ntemp
=
SENSORS_LIMIT
(
temp
,
LM77_TEMP_MIN
,
LM77_TEMP_MAX
);
return
(
u16
)((
ntemp
/
500
)
*
8
)
;
return
(
ntemp
/
500
)
*
8
;
}
}
static
inline
int
LM77_TEMP_FROM_REG
(
u
16
reg
)
static
inline
int
LM77_TEMP_FROM_REG
(
s
16
reg
)
{
{
return
(
(
int
)
reg
/
8
)
*
500
;
return
(
reg
/
8
)
*
500
;
}
}
/* sysfs stuff */
/* sysfs stuff */
...
...
drivers/hwmon/w83792d.c
View file @
b4669d66
...
@@ -303,10 +303,6 @@ struct w83792d_data {
...
@@ -303,10 +303,6 @@ struct w83792d_data {
static
int
w83792d_attach_adapter
(
struct
i2c_adapter
*
adapter
);
static
int
w83792d_attach_adapter
(
struct
i2c_adapter
*
adapter
);
static
int
w83792d_detect
(
struct
i2c_adapter
*
adapter
,
int
address
,
int
kind
);
static
int
w83792d_detect
(
struct
i2c_adapter
*
adapter
,
int
address
,
int
kind
);
static
int
w83792d_detach_client
(
struct
i2c_client
*
client
);
static
int
w83792d_detach_client
(
struct
i2c_client
*
client
);
static
int
w83792d_read_value
(
struct
i2c_client
*
client
,
u8
register
);
static
int
w83792d_write_value
(
struct
i2c_client
*
client
,
u8
register
,
u8
value
);
static
struct
w83792d_data
*
w83792d_update_device
(
struct
device
*
dev
);
static
struct
w83792d_data
*
w83792d_update_device
(
struct
device
*
dev
);
#ifdef DEBUG
#ifdef DEBUG
...
@@ -329,6 +325,20 @@ static inline long in_count_from_reg(int nr, struct w83792d_data *data)
...
@@ -329,6 +325,20 @@ static inline long in_count_from_reg(int nr, struct w83792d_data *data)
return
((
data
->
in
[
nr
]
<<
2
)
|
((
data
->
low_bits
>>
(
2
*
nr
))
&
0x03
));
return
((
data
->
in
[
nr
]
<<
2
)
|
((
data
->
low_bits
>>
(
2
*
nr
))
&
0x03
));
}
}
/* The SMBus locks itself. The Winbond W83792D chip has a bank register,
but the driver only accesses registers in bank 0, so we don't have
to switch banks and lock access between switches. */
static
inline
int
w83792d_read_value
(
struct
i2c_client
*
client
,
u8
reg
)
{
return
i2c_smbus_read_byte_data
(
client
,
reg
);
}
static
inline
int
w83792d_write_value
(
struct
i2c_client
*
client
,
u8
reg
,
u8
value
)
{
return
i2c_smbus_write_byte_data
(
client
,
reg
,
value
);
}
/* following are the sysfs callback functions */
/* following are the sysfs callback functions */
static
ssize_t
show_in
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
static
ssize_t
show_in
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
char
*
buf
)
...
@@ -1386,19 +1396,6 @@ w83792d_detach_client(struct i2c_client *client)
...
@@ -1386,19 +1396,6 @@ w83792d_detach_client(struct i2c_client *client)
return
0
;
return
0
;
}
}
/* The SMBus locks itself. The Winbond W83792D chip has a bank register,
but the driver only accesses registers in bank 0, so we don't have
to switch banks and lock access between switches. */
static
int
w83792d_read_value
(
struct
i2c_client
*
client
,
u8
reg
)
{
return
i2c_smbus_read_byte_data
(
client
,
reg
);
}
static
int
w83792d_write_value
(
struct
i2c_client
*
client
,
u8
reg
,
u8
value
)
{
return
i2c_smbus_write_byte_data
(
client
,
reg
,
value
);
}
static
void
static
void
w83792d_init_client
(
struct
i2c_client
*
client
)
w83792d_init_client
(
struct
i2c_client
*
client
)
{
{
...
...
drivers/i2c/algos/i2c-algo-sibyte.c
View file @
b4669d66
...
@@ -202,7 +202,7 @@ EXPORT_SYMBOL(i2c_sibyte_del_bus);
...
@@ -202,7 +202,7 @@ EXPORT_SYMBOL(i2c_sibyte_del_bus);
#ifdef MODULE
#ifdef MODULE
MODULE_AUTHOR
(
"Kip Walker, Broadcom Corp."
);
MODULE_AUTHOR
(
"Kip Walker, Broadcom Corp."
);
MODULE_DESCRIPTION
(
"SiByte I2C-Bus algorithm"
);
MODULE_DESCRIPTION
(
"SiByte I2C-Bus algorithm"
);
MODULE_PARM
(
bit_scan
,
"i"
);
module_param
(
bit_scan
,
int
,
0
);
MODULE_PARM_DESC
(
bit_scan
,
"Scan for active chips on the bus"
);
MODULE_PARM_DESC
(
bit_scan
,
"Scan for active chips on the bus"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_LICENSE
(
"GPL"
);
...
...
drivers/i2c/busses/Kconfig
View file @
b4669d66
...
@@ -124,6 +124,7 @@ config I2C_I801
...
@@ -124,6 +124,7 @@ config I2C_I801
ICH6
ICH6
ICH7
ICH7
ESB2
ESB2
ICH8
This driver can also be built as a module. If so, the module
This driver can also be built as a module. If so, the module
will be called i2c-i801.
will be called i2c-i801.
...
...
drivers/i2c/busses/i2c-i801.c
View file @
b4669d66
...
@@ -32,6 +32,7 @@
...
@@ -32,6 +32,7 @@
ICH6 266A
ICH6 266A
ICH7 27DA
ICH7 27DA
ESB2 269B
ESB2 269B
ICH8 283E
This driver supports several versions of Intel's I/O Controller Hubs (ICH).
This driver supports several versions of Intel's I/O Controller Hubs (ICH).
For SMBus support, they are similar to the PIIX4 and are part
For SMBus support, they are similar to the PIIX4 and are part
of Intel's '810' and other chipsets.
of Intel's '810' and other chipsets.
...
@@ -527,6 +528,7 @@ static struct pci_device_id i801_ids[] = {
...
@@ -527,6 +528,7 @@ static struct pci_device_id i801_ids[] = {
{
PCI_DEVICE
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_ICH6_16
)
},
{
PCI_DEVICE
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_ICH6_16
)
},
{
PCI_DEVICE
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_ICH7_17
)
},
{
PCI_DEVICE
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_ICH7_17
)
},
{
PCI_DEVICE
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_ESB2_17
)
},
{
PCI_DEVICE
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_ESB2_17
)
},
{
PCI_DEVICE
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_ICH8_5
)
},
{
0
,
}
{
0
,
}
};
};
...
...
drivers/i2c/busses/i2c-parport-light.c
View file @
b4669d66
...
@@ -121,14 +121,11 @@ static struct i2c_adapter parport_adapter = {
...
@@ -121,14 +121,11 @@ static struct i2c_adapter parport_adapter = {
static
int
__init
i2c_parport_init
(
void
)
static
int
__init
i2c_parport_init
(
void
)
{
{
int
type_count
;
if
(
type
<
0
||
type
>=
ARRAY_SIZE
(
adapter_parm
))
{
type_count
=
sizeof
(
adapter_parm
)
/
sizeof
(
struct
adapter_parm
);
if
(
type
<
0
||
type
>=
type_count
)
{
printk
(
KERN_WARNING
"i2c-parport: invalid type (%d)
\n
"
,
type
);
printk
(
KERN_WARNING
"i2c-parport: invalid type (%d)
\n
"
,
type
);
type
=
0
;
type
=
0
;
}
}
if
(
base
==
0
)
{
if
(
base
==
0
)
{
printk
(
KERN_INFO
"i2c-parport: using default base 0x%x
\n
"
,
DEFAULT_BASE
);
printk
(
KERN_INFO
"i2c-parport: using default base 0x%x
\n
"
,
DEFAULT_BASE
);
base
=
DEFAULT_BASE
;
base
=
DEFAULT_BASE
;
...
@@ -152,7 +149,7 @@ static int __init i2c_parport_init(void)
...
@@ -152,7 +149,7 @@ static int __init i2c_parport_init(void)
release_region
(
base
,
3
);
release_region
(
base
,
3
);
return
-
ENODEV
;
return
-
ENODEV
;
}
}
return
0
;
return
0
;
}
}
...
...
drivers/i2c/busses/i2c-parport.c
View file @
b4669d66
...
@@ -241,14 +241,11 @@ static struct parport_driver i2c_parport_driver = {
...
@@ -241,14 +241,11 @@ static struct parport_driver i2c_parport_driver = {
static
int
__init
i2c_parport_init
(
void
)
static
int
__init
i2c_parport_init
(
void
)
{
{
int
type_count
;
if
(
type
<
0
||
type
>=
ARRAY_SIZE
(
adapter_parm
))
{
type_count
=
sizeof
(
adapter_parm
)
/
sizeof
(
struct
adapter_parm
);
if
(
type
<
0
||
type
>=
type_count
)
{
printk
(
KERN_WARNING
"i2c-parport: invalid type (%d)
\n
"
,
type
);
printk
(
KERN_WARNING
"i2c-parport: invalid type (%d)
\n
"
,
type
);
type
=
0
;
type
=
0
;
}
}
return
parport_register_driver
(
&
i2c_parport_driver
);
return
parport_register_driver
(
&
i2c_parport_driver
);
}
}
...
...
drivers/i2c/busses/i2c-pxa.c
View file @
b4669d66
...
@@ -861,7 +861,7 @@ static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id, struct pt_regs *r
...
@@ -861,7 +861,7 @@ static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id, struct pt_regs *r
decode_ISR
(
isr
);
decode_ISR
(
isr
);
}
}
if
(
i2c
->
irqlogidx
<
sizeof
(
i2c
->
isrlog
)
/
sizeof
(
u32
))
if
(
i2c
->
irqlogidx
<
ARRAY_SIZE
(
i2c
->
isrlog
))
i2c
->
isrlog
[
i2c
->
irqlogidx
++
]
=
isr
;
i2c
->
isrlog
[
i2c
->
irqlogidx
++
]
=
isr
;
show_state
(
i2c
);
show_state
(
i2c
);
...
...
drivers/i2c/i2c-core.c
View file @
b4669d66
...
@@ -946,6 +946,20 @@ s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *val
...
@@ -946,6 +946,20 @@ s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *val
}
}
}
}
s32
i2c_smbus_write_i2c_block_data
(
struct
i2c_client
*
client
,
u8
command
,
u8
length
,
u8
*
values
)
{
union
i2c_smbus_data
data
;
if
(
length
>
I2C_SMBUS_BLOCK_MAX
)
length
=
I2C_SMBUS_BLOCK_MAX
;
data
.
block
[
0
]
=
length
;
memcpy
(
data
.
block
+
1
,
values
,
length
);
return
i2c_smbus_xfer
(
client
->
adapter
,
client
->
addr
,
client
->
flags
,
I2C_SMBUS_WRITE
,
command
,
I2C_SMBUS_I2C_BLOCK_DATA
,
&
data
);
}
/* Simulate a SMBus command using the i2c protocol
/* Simulate a SMBus command using the i2c protocol
No checking of parameters is done! */
No checking of parameters is done! */
static
s32
i2c_smbus_xfer_emulated
(
struct
i2c_adapter
*
adapter
,
u16
addr
,
static
s32
i2c_smbus_xfer_emulated
(
struct
i2c_adapter
*
adapter
,
u16
addr
,
...
@@ -1150,6 +1164,7 @@ EXPORT_SYMBOL(i2c_smbus_read_word_data);
...
@@ -1150,6 +1164,7 @@ EXPORT_SYMBOL(i2c_smbus_read_word_data);
EXPORT_SYMBOL
(
i2c_smbus_write_word_data
);
EXPORT_SYMBOL
(
i2c_smbus_write_word_data
);
EXPORT_SYMBOL
(
i2c_smbus_write_block_data
);
EXPORT_SYMBOL
(
i2c_smbus_write_block_data
);
EXPORT_SYMBOL
(
i2c_smbus_read_i2c_block_data
);
EXPORT_SYMBOL
(
i2c_smbus_read_i2c_block_data
);
EXPORT_SYMBOL
(
i2c_smbus_write_i2c_block_data
);
MODULE_AUTHOR
(
"Simon G. Vogl <simon@tk.uni-linz.ac.at>"
);
MODULE_AUTHOR
(
"Simon G. Vogl <simon@tk.uni-linz.ac.at>"
);
MODULE_DESCRIPTION
(
"I2C-Bus main module"
);
MODULE_DESCRIPTION
(
"I2C-Bus main module"
);
...
...
include/linux/i2c.h
View file @
b4669d66
...
@@ -100,6 +100,9 @@ extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
...
@@ -100,6 +100,9 @@ extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
/* Returns the number of read bytes */
/* Returns the number of read bytes */
extern
s32
i2c_smbus_read_i2c_block_data
(
struct
i2c_client
*
client
,
extern
s32
i2c_smbus_read_i2c_block_data
(
struct
i2c_client
*
client
,
u8
command
,
u8
*
values
);
u8
command
,
u8
*
values
);
extern
s32
i2c_smbus_write_i2c_block_data
(
struct
i2c_client
*
client
,
u8
command
,
u8
length
,
u8
*
values
);
/*
/*
* A driver is capable of handling one or more physical devices present on
* A driver is capable of handling one or more physical devices present on
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment