Commit 9323e059 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://linuxusb.bkbits.net/i2c-devel-2.6

into home.osdl.org:/home/torvalds/v2.5/linux
parents a585b007 82a6055f
i2c-velleman driver i2c-velleman driver
------------------- -------------------
This is a driver for i2c-hw access for Velleman K9000 and other adapters. This is a driver for i2c-hw access for Velleman K8000 and other adapters.
Useful links Useful links
------------ ------------
...@@ -10,18 +10,14 @@ Velleman: ...@@ -10,18 +10,14 @@ Velleman:
Velleman K8000 Howto: Velleman K8000 Howto:
http://howto.htlw16.ac.at/k8000-howto.html http://howto.htlw16.ac.at/k8000-howto.html
K8000 and K8005 libraries K8000 and K8005 libraries
------------------------- -------------------------
The project has lead to new libs for the Velleman K8000 and K8005.. The project has lead to new libs for the Velleman K8000 and K8005:
LIBK8000 v1.99.1 and LIBK8005 v0.21 LIBK8000 v1.99.1 and LIBK8005 v0.21
With these libs you can control the K8000 and K8005 with the original With these libs, you can control the K8000 interface card and the K8005
simple commands which are in the original Velleman software. stepper motor card with the simple commands which are in the original
Like SetIOchannel, ReadADchannel, SendStepCCWFull and many more. Velleman software, like SetIOchannel, ReadADchannel, SendStepCCWFull and
Via i2c kernel device /dev/velleman many more, using /dev/velleman.
The libs can be found on http://groups.yahoo.com/group/k8000/files/linux/ The libs can be found on http://groups.yahoo.com/group/k8000/files/linux/
The Velleman K8000 interface card on http://www.velleman.be/kits/k8000.htm
The Velleman K8005 steppermotorcard on http://www.velleman.be/kits/k8005.htm
Revision 3, 2003-10-04
Jean Delvare <khali@linux-fr.org>
Greg KH <greg@kroah.com>
This is a guide on how to convert I2C chip drivers from Linux 2.4 to
Linux 2.6. I have been using existing drivers (lm75, lm78) as examples.
Then I converted a driver myself (lm83) and updated this document.
There are two sets of points below. The first set concerns technical
changes. The second set concerns coding policy. Both are mandatory.
Although reading this guide will help you porting drivers, I suggest
you keep an eye on an already ported driver while porting your own
driver. This will help you a lot understanding what this guide
exactly means. Choose the chip driver that is the more similar to
yours for best results.
Technical changes:
* [Includes] Get rid of "version.h". Replace <linux/i2c-proc.h> with
<linux/i2c-sensor.h>. Includes typically look like that:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
#include <linux/i2c-vid.h> /* if you need VRM support */
#include <asm/io.h> /* if you have I/O operations */
Some extra headers may be required for a given driver.
* [Addresses] SENSORS_I2C_END becomes I2C_CLIENT_END, SENSORS_ISA_END
becomes I2C_CLIENT_ISA_END.
* [Client data] Get rid of sysctl_id. Try using standard names for
register values (for example, temp_os becomes temp_max). You're
still relatively free here, but you *have* to follow the standard
names for sysfs files (see the Sysctl section below).
* [Function prototypes] The detect functions loses its flags
parameter. Sysctl (e.g. lm75_temp) and miscellaneous (e.g.
swap_bytes) functions are off the list of prototypes. This
usually leaves five prototypes:
static int lm75_attach_adapter(struct i2c_adapter *adapter);
static int lm75_detect(struct i2c_adapter *adapter, int address,
int kind);
static void lm75_init_client(struct i2c_client *client);
static int lm75_detach_client(struct i2c_client *client);
static void lm75_update_client(struct i2c_client *client);
* [Sysctl] All sysctl stuff is of course gone (defines, ctl_table
and functions). Instead, right after the static id definition
line, you have to define show and set functions for each sysfs
file. Only define set for writable values. Take a look at an
existing 2.6 driver for details (lm78 for example). Don't forget
to define the attributes for each file (this is that step that
links callback functions). Use the file names specified in
Documentation/i2c/sysfs-interface for the individual files. Also
convert the units these files read and write to the specified ones.
If you need to add a new type of file, please discuss it on the
sensors mailing list <sensors@stimpy.netroedge.com> by providing a
patch to the Documentation/i2c/sysfs-interface file.
* [Attach] For I2C drivers, the attach function should make sure
that the adapter's class has I2C_ADAP_CLASS_SMBUS, using the
following construct:
if (!(adapter->class & I2C_ADAP_CLASS_SMBUS))
return 0;
ISA-only drivers of course don't need this.
* [Detect] As mentioned earlier, the flags parameter is gone.
The type_name and client_name strings are replaced by a single
name string, which will be filled with a lowercase, short string
(typically the driver name, e.g. "lm75"). The errorN labels are
reduced to the number needed. If that number is 2 (i2c-only
drivers), it is advised that the labels are named exit and
exit_free. For i2c+isa drivers, labels should be named ERROR0,
ERROR1 and ERROR2. Don't forget to properly set err before
jumping to error labels. By the way, labels should be
left-aligned.
Use memset to fill the client and data area with 0x00.
Use i2c_set_clientdata to set the client data (as opposed to
a direct access to client->data).
Use strlcpy instead of strcpy to copy the client name.
Replace the sysctl directory registration by calls to
device_create_file. Move the driver initialization before any
sysfs file creation.
* [Detach] Get rid of data, remove the call to
i2c_deregister_entry.
* [Update] Don't access client->data directly, use
i2c_get_clientdata(client) instead.
* [Interface] Init function should not print anything. Make sure
there is a MODULE_LICENSE() line.
Coding policy:
* [Copyright] Use (C), not (c), for copyright.
* [Debug/log] Get rid of #ifdef DEBUG/#endif constructs whenever you
can. Calls to printk/pr_debug for debugging purposes are replaced
by calls to dev_dbg. Here is an example on how to call it (taken
from lm75_detect):
dev_dbg(&adapter->dev,
"lm75_detect called for an ISA bus adapter?!?\n");
Replace other printk calls with the dev_info, dev_err or dev_warn
function, as appropriate.
* [Constants] Constants defines (registers, conversions, initial
values) should be aligned. This greatly improves readability.
Same goes for variables declarations. Alignments are achieved by the
means of tabs, not spaces. Remember that tabs are set to 8 in the
Linux kernel code.
* [Structure definition] The name field should be standardized. All
lowercase and as simple as the driver name itself (e.g. "lm75").
* [Layout] Avoid extra empty lines between comments and what they
comment. Respect the coding style (see Documentation/CodingStyle),
in particular when it comes to placing curly braces.
...@@ -71,5 +71,5 @@ i2c-philips-par: Philips style parallel port adapter (uses i2c-algo-bit) ...@@ -71,5 +71,5 @@ i2c-philips-par: Philips style parallel port adapter (uses i2c-algo-bit)
i2c-adap-ibm_ocp: IBM 4xx processor I2C device (uses i2c-algo-ibm_ocp) (NOT BUILT BY DEFAULT) i2c-adap-ibm_ocp: IBM 4xx processor I2C device (uses i2c-algo-ibm_ocp) (NOT BUILT BY DEFAULT)
i2c-pport: Primitive parallel port adapter (uses i2c-algo-bit) i2c-pport: Primitive parallel port adapter (uses i2c-algo-bit)
i2c-rpx: RPX board Motorola 8xx I2C device (uses i2c-algo-8xx) (NOT BUILT BY DEFAULT) i2c-rpx: RPX board Motorola 8xx I2C device (uses i2c-algo-8xx) (NOT BUILT BY DEFAULT)
i2c-velleman: Velleman K9000 parallel port adapter (uses i2c-algo-bit) i2c-velleman: Velleman K8000 parallel port adapter (uses i2c-algo-bit)
...@@ -68,9 +68,7 @@ curr_max[1-n] Current max value ...@@ -68,9 +68,7 @@ curr_max[1-n] Current max value
Fixed point XXXXX, divide by 1000 to get Amps. Fixed point XXXXX, divide by 1000 to get Amps.
Read/Write. Read/Write.
curr_min[1-n] Current min or hysteresis value. curr_min[1-n] Current min value.
Preferably a hysteresis value, reported as a absolute
current, NOT a delta from the max value.
Fixed point XXXXX, divide by 1000 to get Amps. Fixed point XXXXX, divide by 1000 to get Amps.
Read/Write. Read/Write.
...@@ -144,25 +142,38 @@ sensor[1-3] Sensor type selection. ...@@ -144,25 +142,38 @@ sensor[1-3] Sensor type selection.
Integers 1,2,3, or thermistor Beta value (3435) Integers 1,2,3, or thermistor Beta value (3435)
Read/Write. Read/Write.
temp_max[1-3] Temperature max value. temp_max[1-4] Temperature max value.
Fixed point value in form XXXXX and should be divided by Fixed point value in form XXXXX and should be divided by
1000 to get degrees Celsius. 1000 to get degrees Celsius.
Read/Write value. Read/Write value.
temp_min[1-3] Temperature min or hysteresis value. temp_min[1-3] Temperature min value.
Fixed point value in form XXXXX and should be divided by Fixed point value in form XXXXX and should be divided by
1000 to get degrees Celsius. This is preferably a 1000 to get degrees Celsius.
hysteresis value, reported as a absolute temperature,
NOT a delta from the max value.
Read/Write value. Read/Write value.
temp_input[1-3] Temperature input value. temp_hyst[1-3] Temperature hysteresis value.
Fixed point value in form XXXXX and should be divided by
1000 to get degrees Celsius. Must be reported as an
absolute temperature, NOT a delta from the max value.
Read/Write value.
temp_input[1-4] Temperature input value.
Fixed point value in form XXXXX and should be divided by
1000 to get degrees Celsius.
Read only value. Read only value.
temp_crit Temperature critical value, typically greater than all
temp_max values.
Fixed point value in form XXXXX and should be divided by
1000 to get degrees Celsius.
Common to all temperature channels.
Read/Write value.
If there are multiple temperature sensors, temp_*1 is If there are multiple temperature sensors, temp_*1 is
generally the sensor inside the chip itself, generally generally the sensor inside the chip itself, generally
reported as "motherboard temperature". temp_*2 and reported as "motherboard temperature". temp_*2 to
temp_*3 are generally sensors external to the chip temp_*4 are generally sensors external to the chip
itself, for example the thermal diode inside the CPU or itself, for example the thermal diode inside the CPU or
a thermistor nearby. a thermistor nearby.
......
...@@ -24,16 +24,14 @@ all clients from it. Remember, a driver structure contains general access ...@@ -24,16 +24,14 @@ all clients from it. Remember, a driver structure contains general access
routines, a client structure specific information like the actual I2C routines, a client structure specific information like the actual I2C
address. address.
struct i2c_driver foo_driver static struct i2c_driver foo_driver = {
{ .owner = THIS_MODULE,
/* name */ "Foo version 2.3 and later driver", .name = "Foo version 2.3 driver",
/* id */ I2C_DRIVERID_FOO, .id = I2C_DRIVERID_FOO, /* usually from i2c-id.h */
/* flags */ I2C_DF_NOTIFY, .flags = I2C_DF_NOTIFY,
/* attach_adapter */ &foo_attach_adapter, .attach_adapter = &foo_attach_adapter,
/* detach_client */ &foo_detach_client, .detach_client = &foo_detach_client,
/* command */ &foo_command, /* May be NULL */ .command = &foo_command /* may be NULL */
/* inc_use */ &foo_inc_use, /* May be NULL */
/* dec_use */ &foo_dec_use /* May be NULL */
} }
The name can be chosen freely, and may be upto 40 characters long. Please The name can be chosen freely, and may be upto 40 characters long. Please
...@@ -50,43 +48,8 @@ This is almost always what you want. ...@@ -50,43 +48,8 @@ This is almost always what you want.
All other fields are for call-back functions which will be explained All other fields are for call-back functions which will be explained
below. below.
There use to be two additional fields in this structure, inc_use et dec_use,
Module usage count for module usage count, but these fields were obsoleted and removed.
==================
If your driver can also be compiled as a module, there are moments at
which the module can not be removed from memory. For example, when you
are doing a lengthy transaction, or when you create a /proc directory,
and some process has entered that directory (this last case is the
main reason why these call-backs were introduced).
To increase or decrease the module usage count, you can use the
MOD_{INC,DEC}_USE_COUNT macros. They must be called from the module
which needs to get its usage count changed; that is why each driver
module has to implement its own callback.
void foo_inc_use (struct i2c_client *client)
{
#ifdef MODULE
MOD_INC_USE_COUNT;
#endif
}
void foo_dec_use (struct i2c_client *client)
{
#ifdef MODULE
MOD_DEC_USE_COUNT;
#endif
}
Do not call these call-back functions directly; instead, use one of the
following functions defined in i2c.h:
void i2c_inc_use_client(struct i2c_client *);
void i2c_dec_use_client(struct i2c_client *);
You should *not* increase the module count just because a device is
detected and a client created. This would make it impossible to remove
an adapter driver!
Extra client data Extra client data
......
...@@ -18,10 +18,8 @@ ...@@ -18,10 +18,8 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* With some changes from Kysti Mlkki <kmalkki@cc.hut.fi> and even /* With some changes from Frodo Looijaard <frodol@dds.nl>, Kysti Mlkki
Frodo Looijaard <frodol@dds.nl> */ <kmalkki@cc.hut.fi> and Jean Delvare <khali@linux-fr.org> */
/* $Id: i2c-algo-bit.c,v 1.44 2003/01/21 08:08:16 kmalkki Exp $ */
/* #define DEBUG 1 */ /* #define DEBUG 1 */
...@@ -87,8 +85,10 @@ static inline int sclhi(struct i2c_algo_bit_data *adap) ...@@ -87,8 +85,10 @@ static inline int sclhi(struct i2c_algo_bit_data *adap)
setscl(adap,1); setscl(adap,1);
/* Not all adapters have scl sense line... */ /* Not all adapters have scl sense line... */
if (adap->getscl == NULL ) if (adap->getscl == NULL ) {
udelay(adap->udelay);
return 0; return 0;
}
start=jiffies; start=jiffies;
while (! getscl(adap) ) { while (! getscl(adap) ) {
...@@ -222,68 +222,72 @@ static int i2c_inb(struct i2c_adapter *i2c_adap) ...@@ -222,68 +222,72 @@ static int i2c_inb(struct i2c_adapter *i2c_adap)
*/ */
static int test_bus(struct i2c_algo_bit_data *adap, char* name) { static int test_bus(struct i2c_algo_bit_data *adap, char* name) {
int scl,sda; int scl,sda;
if (adap->getscl==NULL)
printk(KERN_INFO "i2c-algo-bit.o: Testing SDA only, "
"SCL is not readable.\n");
sda=getsda(adap); sda=getsda(adap);
if (adap->getscl==NULL) { scl=(adap->getscl==NULL?1:getscl(adap));
printk(KERN_WARNING "i2c-algo-bit.o: Warning: Adapter can't read from clock line - skipping test.\n"); printk(KERN_DEBUG "i2c-algo-bit.o: (0) scl=%d, sda=%d\n",scl,sda);
return 0;
}
scl=getscl(adap);
printk(KERN_INFO "i2c-algo-bit.o: Adapter: %s scl: %d sda: %d -- testing...\n",
name,getscl(adap),getsda(adap));
if (!scl || !sda ) { if (!scl || !sda ) {
printk(KERN_INFO " i2c-algo-bit.o: %s seems to be busy.\n",name); printk(KERN_WARNING "i2c-algo-bit.o: %s seems to be busy.\n", name);
goto bailout; goto bailout;
} }
sdalo(adap); sdalo(adap);
printk(KERN_DEBUG "i2c-algo-bit.o:1 scl: %d sda: %d \n",getscl(adap), sda=getsda(adap);
getsda(adap)); scl=(adap->getscl==NULL?1:getscl(adap));
if ( 0 != getsda(adap) ) { printk(KERN_DEBUG "i2c-algo-bit.o: (1) scl=%d, sda=%d\n",scl,sda);
printk(KERN_WARNING "i2c-algo-bit.o: %s SDA stuck high!\n",name); if ( 0 != sda ) {
sdahi(adap); printk(KERN_WARNING "i2c-algo-bit.o: SDA stuck high!\n");
goto bailout; goto bailout;
} }
if ( 0 == getscl(adap) ) { if ( 0 == scl ) {
printk(KERN_WARNING "i2c-algo-bit.o: %s SCL unexpected low while pulling SDA low!\n", printk(KERN_WARNING "i2c-algo-bit.o: SCL unexpected low "
name); "while pulling SDA low!\n");
goto bailout; goto bailout;
} }
sdahi(adap); sdahi(adap);
printk(KERN_DEBUG "i2c-algo-bit.o:2 scl: %d sda: %d \n",getscl(adap), sda=getsda(adap);
getsda(adap)); scl=(adap->getscl==NULL?1:getscl(adap));
if ( 0 == getsda(adap) ) { printk(KERN_DEBUG "i2c-algo-bit.o: (2) scl=%d, sda=%d\n",scl,sda);
printk(KERN_WARNING "i2c-algo-bit.o: %s SDA stuck low!\n",name); if ( 0 == sda ) {
sdahi(adap); printk(KERN_WARNING "i2c-algo-bit.o: SDA stuck low!\n");
goto bailout; goto bailout;
} }
if ( 0 == getscl(adap) ) { if ( 0 == scl ) {
printk(KERN_WARNING "i2c-algo-bit.o: %s SCL unexpected low while SDA high!\n", printk(KERN_WARNING "i2c-algo-bit.o: SCL unexpected low "
name); "while pulling SDA high!\n");
goto bailout; goto bailout;
} }
scllo(adap); scllo(adap);
printk(KERN_DEBUG "i2c-algo-bit.o:3 scl: %d sda: %d \n",getscl(adap), sda=getsda(adap);
getsda(adap)); scl=(adap->getscl==NULL?0:getscl(adap));
if ( 0 != getscl(adap) ) { printk(KERN_DEBUG "i2c-algo-bit.o: (3) scl=%d, sda=%d\n",scl,sda);
printk(KERN_WARNING "i2c-algo-bit.o: %s SCL stuck high!\n",name); if ( 0 != scl ) {
sclhi(adap); printk(KERN_WARNING "i2c-algo-bit.o: SCL stuck high!\n");
goto bailout; goto bailout;
} }
if ( 0 == getsda(adap) ) { if ( 0 == sda ) {
printk(KERN_WARNING "i2c-algo-bit.o: %s SDA unexpected low while pulling SCL low!\n", printk(KERN_WARNING "i2c-algo-bit.o: SDA unexpected low "
name); "while pulling SCL low!\n");
goto bailout; goto bailout;
} }
sclhi(adap); sclhi(adap);
printk(KERN_DEBUG "i2c-algo-bit.o:4 scl: %d sda: %d \n",getscl(adap), sda=getsda(adap);
getsda(adap)); scl=(adap->getscl==NULL?1:getscl(adap));
if ( 0 == getscl(adap) ) { printk(KERN_DEBUG "i2c-algo-bit.o: (4) scl=%d, sda=%d\n",scl,sda);
printk(KERN_WARNING "i2c-algo-bit.o: %s SCL stuck low!\n",name); if ( 0 == scl ) {
sclhi(adap); printk(KERN_WARNING "i2c-algo-bit.o: SCL stuck low!\n");
goto bailout; goto bailout;
} }
if ( 0 == getsda(adap) ) { if ( 0 == sda ) {
printk(KERN_WARNING "i2c-algo-bit.o: %s SDA unexpected low while SCL high!\n", printk(KERN_WARNING "i2c-algo-bit.o: SDA unexpected low "
name); "while pulling SCL high!\n");
goto bailout; goto bailout;
} }
printk(KERN_INFO "i2c-algo-bit.o: %s passed test.\n",name); printk(KERN_INFO "i2c-algo-bit.o: %s passed test.\n",name);
......
...@@ -60,27 +60,13 @@ ...@@ -60,27 +60,13 @@
/* debug the protocol by showing transferred bits */ /* debug the protocol by showing transferred bits */
#define DEF_TIMEOUT 16 #define DEF_TIMEOUT 16
/* debugging - slow down transfer to have a look at the data .. */
/* I use this with two leds&resistors, each one connected to sda,scl */
/* respectively. This makes sure that the algorithm works. Some chips */
/* might not like this, as they have an internal timeout of some mils */
/*
#define SLO_IO jif=jiffies;while(jiffies<=jif+i2c_table[minor].veryslow)\
cond_resched();
*/
/* ----- global variables --------------------------------------------- */ /* ----- global variables --------------------------------------------- */
#ifdef SLO_IO
int jif;
#endif
/* module parameters: /* module parameters:
*/ */
static int i2c_debug=1; static int i2c_debug=1;
static int iic_test=0; /* see if the line-setting functions work */ static int iic_test=0; /* see if the line-setting functions work */
static int iic_scan=0; /* have a look at what's hanging 'round */
/* --- setting states on the bus with the right timing: --------------- */ /* --- setting states on the bus with the right timing: --------------- */
...@@ -757,8 +743,6 @@ static struct i2c_algorithm iic_algo = { ...@@ -757,8 +743,6 @@ static struct i2c_algorithm iic_algo = {
*/ */
int i2c_iic_add_bus(struct i2c_adapter *adap) int i2c_iic_add_bus(struct i2c_adapter *adap)
{ {
int i;
short status;
struct i2c_algo_iic_data *iic_adap = adap->algo_data; struct i2c_algo_iic_data *iic_adap = adap->algo_data;
if (iic_test) { if (iic_test) {
...@@ -782,24 +766,6 @@ int i2c_iic_add_bus(struct i2c_adapter *adap) ...@@ -782,24 +766,6 @@ int i2c_iic_add_bus(struct i2c_adapter *adap)
i2c_add_adapter(adap); i2c_add_adapter(adap);
iic_init(iic_adap); iic_init(iic_adap);
/* scan bus */
/* By default scanning the bus is turned off. */
if (iic_scan) {
printk(KERN_INFO " i2c-algo-ite: scanning bus %s.\n",
adap->name);
for (i = 0x00; i < 0xff; i+=2) {
iic_outw(iic_adap, ITE_I2CSAR, i);
iic_start(iic_adap);
if ( (wait_for_pin(iic_adap, &status) == 0) &&
((status & ITE_I2CHSR_DNE) == 0) ) {
printk(KERN_INFO "\n(%02x)\n",i>>1);
} else {
printk(KERN_INFO ".");
iic_reset(iic_adap);
}
udelay(iic_adap->udelay);
}
}
return 0; return 0;
} }
...@@ -839,11 +805,9 @@ MODULE_DESCRIPTION("ITE iic algorithm"); ...@@ -839,11 +805,9 @@ MODULE_DESCRIPTION("ITE iic algorithm");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_PARM(iic_test, "i"); MODULE_PARM(iic_test, "i");
MODULE_PARM(iic_scan, "i");
MODULE_PARM(i2c_debug,"i"); MODULE_PARM(i2c_debug,"i");
MODULE_PARM_DESC(iic_test, "Test if the I2C bus is available"); MODULE_PARM_DESC(iic_test, "Test if the I2C bus is available");
MODULE_PARM_DESC(iic_scan, "Scan for active chips on the bus");
MODULE_PARM_DESC(i2c_debug, MODULE_PARM_DESC(i2c_debug,
"debug level - 0 off; 1 normal; 2,3 more verbose; 9 iic-protocol"); "debug level - 0 off; 1 normal; 2,3 more verbose; 9 iic-protocol");
......
...@@ -161,11 +161,12 @@ config I2C_PIIX4 ...@@ -161,11 +161,12 @@ config I2C_PIIX4
help help
If you say yes to this option, support will be included for the Intel If you say yes to this option, support will be included for the Intel
PIIX4 family of mainboard I2C interfaces. Specifically, the following PIIX4 family of mainboard I2C interfaces. Specifically, the following
versions of the chipset is supported: versions of the chipset are supported:
Intel PIIX4 Intel PIIX4
Intel 440MX Intel 440MX
Serverworks OSB4 Serverworks OSB4
Serverworks CSB5 Serverworks CSB5
Serverworks CSB6
SMSC Victory66 SMSC Victory66
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
...@@ -201,7 +202,7 @@ config I2C_SAVAGE4 ...@@ -201,7 +202,7 @@ config I2C_SAVAGE4
config SCx200_I2C config SCx200_I2C
tristate "NatSemi SCx200 I2C using GPIO pins" tristate "NatSemi SCx200 I2C using GPIO pins"
depends on SCx200 && I2C_ALGOBIT depends on SCx200_GPIO && I2C_ALGOBIT
help help
Enable the use of two GPIO pins of a SCx200 processor as an I2C bus. Enable the use of two GPIO pins of a SCx200 processor as an I2C bus.
...@@ -228,7 +229,7 @@ config SCx200_I2C_SDA ...@@ -228,7 +229,7 @@ config SCx200_I2C_SDA
config SCx200_ACB config SCx200_ACB
tristate "NatSemi SCx200 ACCESS.bus" tristate "NatSemi SCx200 ACCESS.bus"
depends on I2C_ALGOBIT!=n && I2C depends on I2C
help help
Enable the use of the ACCESS.bus controllers of a SCx200 processor. Enable the use of the ACCESS.bus controllers of a SCx200 processor.
...@@ -275,10 +276,10 @@ config I2C_SIS96X ...@@ -275,10 +276,10 @@ config I2C_SIS96X
will be called i2c-sis96x. will be called i2c-sis96x.
config I2C_VELLEMAN config I2C_VELLEMAN
tristate "Velleman K9000 adapter" tristate "Velleman K8000 adapter"
depends on I2C_ALGOBIT && ISA depends on I2C_ALGOBIT && ISA
help help
This supports the Velleman K9000 parallel-port I2C adapter. Say Y This supports the Velleman K8000 parallel-port I2C adapter. Say Y
if you own such an adapter. if you own such an adapter.
This support is also available as a module. If so, the module This support is also available as a module. If so, the module
...@@ -309,6 +310,7 @@ config I2C_VIAPRO ...@@ -309,6 +310,7 @@ config I2C_VIAPRO
8233 8233
8233A 8233A
8235 8235
8237
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-viapro. will be called i2c-viapro.
......
...@@ -28,10 +28,12 @@ ...@@ -28,10 +28,12 @@
2002-04-08: Added nForce support. (Csaba Halasz) 2002-04-08: Added nForce support. (Csaba Halasz)
2002-10-03: Fixed nForce PnP I/O port. (Michael Steil) 2002-10-03: Fixed nForce PnP I/O port. (Michael Steil)
2002-12-28: Rewritten into something that resembles a Linux driver (hch) 2002-12-28: Rewritten into something that resembles a Linux driver (hch)
2003-11-29: Added back AMD8111 removed by the previous rewrite.
(Philip Pokorny)
*/ */
/* /*
Supports AMD756, AMD766, AMD768 and nVidia nForce Supports AMD756, AMD766, AMD768, AMD8111 and nVidia nForce
Note: we assume there can only be one device, with one SMBus interface. Note: we assume there can only be one device, with one SMBus interface.
*/ */
...@@ -213,9 +215,8 @@ static s32 amd756_access(struct i2c_adapter * adap, u16 addr, ...@@ -213,9 +215,8 @@ static s32 amd756_access(struct i2c_adapter * adap, u16 addr,
case I2C_SMBUS_BYTE: case I2C_SMBUS_BYTE:
outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
SMB_HOST_ADDRESS); SMB_HOST_ADDRESS);
/* TODO: Why only during write? */
if (read_write == I2C_SMBUS_WRITE) if (read_write == I2C_SMBUS_WRITE)
outb_p(command, SMB_HOST_COMMAND); outb_p(command, SMB_HOST_DATA);
size = AMD756_BYTE; size = AMD756_BYTE;
break; break;
case I2C_SMBUS_BYTE_DATA: case I2C_SMBUS_BYTE_DATA:
...@@ -308,12 +309,13 @@ static struct i2c_adapter amd756_adapter = { ...@@ -308,12 +309,13 @@ static struct i2c_adapter amd756_adapter = {
.name = "unset", .name = "unset",
}; };
enum chiptype { AMD756, AMD766, AMD768, NFORCE }; enum chiptype { AMD756, AMD766, AMD768, NFORCE, AMD8111 };
static struct pci_device_id amd756_ids[] = { static struct pci_device_id amd756_ids[] = {
{PCI_VENDOR_ID_AMD, 0x740B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD756 }, {PCI_VENDOR_ID_AMD, 0x740B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD756 },
{PCI_VENDOR_ID_AMD, 0x7413, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD766 }, {PCI_VENDOR_ID_AMD, 0x7413, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD766 },
{PCI_VENDOR_ID_AMD, 0x7443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD768 }, {PCI_VENDOR_ID_AMD, 0x7443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD768 },
{PCI_VENDOR_ID_AMD, 0x746B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD8111 },
{PCI_VENDOR_ID_NVIDIA, 0x01B4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NFORCE }, {PCI_VENDOR_ID_NVIDIA, 0x01B4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NFORCE },
{ 0, } { 0, }
}; };
...@@ -321,7 +323,8 @@ static struct pci_device_id amd756_ids[] = { ...@@ -321,7 +323,8 @@ static struct pci_device_id amd756_ids[] = {
static int __devinit amd756_probe(struct pci_dev *pdev, static int __devinit amd756_probe(struct pci_dev *pdev,
const struct pci_device_id *id) const struct pci_device_id *id)
{ {
int nforce = (id->driver_data == NFORCE), error; int nforce = (id->driver_data == NFORCE);
int error;
u8 temp; u8 temp;
if (amd756_ioport) { if (amd756_ioport) {
...@@ -368,7 +371,7 @@ static int __devinit amd756_probe(struct pci_dev *pdev, ...@@ -368,7 +371,7 @@ static int __devinit amd756_probe(struct pci_dev *pdev,
amd756_adapter.dev.parent = &pdev->dev; amd756_adapter.dev.parent = &pdev->dev;
snprintf(amd756_adapter.name, I2C_NAME_SIZE, snprintf(amd756_adapter.name, I2C_NAME_SIZE,
"SMBus AMD75x adapter at %04x", amd756_ioport); "SMBus AMD756 adapter at %04x", amd756_ioport);
error = i2c_add_adapter(&amd756_adapter); error = i2c_add_adapter(&amd756_adapter);
if (error) { if (error) {
...@@ -391,7 +394,7 @@ static void __devexit amd756_remove(struct pci_dev *dev) ...@@ -391,7 +394,7 @@ static void __devexit amd756_remove(struct pci_dev *dev)
} }
static struct pci_driver amd756_driver = { static struct pci_driver amd756_driver = {
.name = "amd75x smbus", .name = "amd756 smbus",
.id_table = amd756_ids, .id_table = amd756_ids,
.probe = amd756_probe, .probe = amd756_probe,
.remove = __devexit_p(amd756_remove), .remove = __devexit_p(amd756_remove),
...@@ -408,7 +411,7 @@ static void __exit amd756_exit(void) ...@@ -408,7 +411,7 @@ static void __exit amd756_exit(void)
} }
MODULE_AUTHOR("Merlin Hughes <merlin@merlin.org>"); MODULE_AUTHOR("Merlin Hughes <merlin@merlin.org>");
MODULE_DESCRIPTION("AMD756/766/768/nVidia nForce SMBus driver"); MODULE_DESCRIPTION("AMD756/766/768/8111 and nVidia nForce SMBus driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
module_init(amd756_init) module_init(amd756_init)
......
...@@ -192,7 +192,7 @@ s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, ...@@ -192,7 +192,7 @@ s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short flags,
case I2C_SMBUS_BYTE: case I2C_SMBUS_BYTE:
if (read_write == I2C_SMBUS_WRITE) if (read_write == I2C_SMBUS_WRITE)
amd_ec_write(smbus, AMD_SMB_DATA, data->byte); amd_ec_write(smbus, AMD_SMB_CMD, command);
protocol |= AMD_SMB_PRTCL_BYTE; protocol |= AMD_SMB_PRTCL_BYTE;
break; break;
......
...@@ -48,10 +48,6 @@ ...@@ -48,10 +48,6 @@
MODULE_DESCRIPTION("IBM IIC driver v" DRIVER_VERSION); MODULE_DESCRIPTION("IBM IIC driver v" DRIVER_VERSION);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static int iic_scan = 0;
MODULE_PARM(iic_scan, "i");
MODULE_PARM_DESC(iic_scan, "Scan for active chips on the bus");
static int iic_force_poll = 0; static int iic_force_poll = 0;
MODULE_PARM(iic_force_poll, "i"); MODULE_PARM(iic_force_poll, "i");
MODULE_PARM_DESC(iic_force_poll, "Force polling mode"); MODULE_PARM_DESC(iic_force_poll, "Force polling mode");
...@@ -517,32 +513,6 @@ static struct i2c_algorithm iic_algo = { ...@@ -517,32 +513,6 @@ static struct i2c_algorithm iic_algo = {
.functionality = iic_func .functionality = iic_func
}; };
/*
* Scan bus for valid 7-bit addresses (ie things that ACK on 1 byte read)
* We only scan range [0x08 - 0x77], all other addresses are reserved anyway
*/
static void __devinit iic_scan_bus(struct ibm_iic_private* dev)
{
int found = 0;
char dummy;
struct i2c_msg msg = {
.buf = &dummy,
.len = sizeof(dummy),
.flags = I2C_M_RD
};
printk(KERN_INFO "ibm-iic%d: scanning bus...\n" KERN_INFO, dev->idx);
for (msg.addr = 8; msg.addr < 0x78; ++msg.addr)
if (iic_xfer(&dev->adap, &msg, 1) == 1){
++found;
printk(" 0x%02x", msg.addr);
}
printk("%sibm-iic%d: %d device(s) detected\n",
found ? "\n" KERN_INFO : "", dev->idx, found);
}
/* /*
* Calculates IICx_CLCKDIV value for a specific OPB clock frequency * Calculates IICx_CLCKDIV value for a specific OPB clock frequency
*/ */
...@@ -649,10 +619,6 @@ static int __devinit iic_probe(struct ocp_device *ocp){ ...@@ -649,10 +619,6 @@ static int __devinit iic_probe(struct ocp_device *ocp){
printk(KERN_INFO "ibm-iic%d: using %s mode\n", dev->idx, printk(KERN_INFO "ibm-iic%d: using %s mode\n", dev->idx,
dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)"); dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");
/* Scan bus if requested by user */
if (iic_scan)
iic_scan_bus(dev);
return 0; return 0;
fail: fail:
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
/* /*
Supports: Supports:
Intel PIIX4, 440MX Intel PIIX4, 440MX
Serverworks OSB4, CSB5 Serverworks OSB4, CSB5, CSB6
SMSC Victory66 SMSC Victory66
Note: we assume there can only be one device, with one SMBus interface. Note: we assume there can only be one device, with one SMBus interface.
...@@ -99,6 +99,13 @@ MODULE_PARM_DESC(force_addr, ...@@ -99,6 +99,13 @@ MODULE_PARM_DESC(force_addr,
"Forcibly enable the PIIX4 at the given address. " "Forcibly enable the PIIX4 at the given address. "
"EXTREMELY DANGEROUS!"); "EXTREMELY DANGEROUS!");
/* If fix_hstcfg is set to anything different from 0, we reset one of the
registers to be a valid value. */
static int fix_hstcfg = 0;
MODULE_PARM(fix_hstcfg, "i");
MODULE_PARM_DESC(fix_hstcfg,
"Fix config register. Needed on some boards (Force CPCI735).");
static int piix4_transaction(void); static int piix4_transaction(void);
...@@ -164,9 +171,17 @@ static int piix4_setup(struct pci_dev *PIIX4_dev, const struct pci_device_id *id ...@@ -164,9 +171,17 @@ static int piix4_setup(struct pci_dev *PIIX4_dev, const struct pci_device_id *id
/* Some BIOS will set up the chipset incorrectly and leave a register /* Some BIOS will set up the chipset incorrectly and leave a register
in an undefined state (causing I2C to act very strangely). */ in an undefined state (causing I2C to act very strangely). */
if (temp & 0x02) { if (temp & 0x02) {
dev_info(&PIIX4_dev->dev, "Worked around buggy BIOS (I2C)\n"); if (fix_hstcfg) {
temp = temp & 0xfd; dev_info(&PIIX4_dev->dev, "Working around buggy BIOS "
pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp); "(I2C)\n");
temp &= 0xfd;
pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp);
} else {
dev_info(&PIIX4_dev->dev, "Unusual config register "
"value\n");
dev_info(&PIIX4_dev->dev, "Try using fix_hstcfg=1 if "
"you experience problems\n");
}
} }
/* If force_addr is set, we program the new address here. Just to make /* If force_addr is set, we program the new address here. Just to make
...@@ -422,6 +437,13 @@ static struct pci_device_id piix4_ids[] = { ...@@ -422,6 +437,13 @@ static struct pci_device_id piix4_ids[] = {
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.driver_data = 0, .driver_data = 0,
}, },
{
.vendor = PCI_VENDOR_ID_SERVERWORKS,
.device = PCI_DEVICE_ID_SERVERWORKS_CSB6,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.driver_data = 0,
},
{ {
.vendor = PCI_VENDOR_ID_INTEL, .vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_82443MX_3, .device = PCI_DEVICE_ID_INTEL_82443MX_3,
......
/* /*
i2c-savage4.c - Part of lm_sensors, Linux kernel modules for hardware i2c-savage4.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring monitoring
Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>, Copyright (C) 1998-2003 The LM Sensors Team
Philip Edelbrock <phil@netroedge.com>, Alexander Wold <awold@bigfoot.com>
Ralph Metzler <rjkm@thp.uni-koeln.de>, and
Mark D. Studebaker <mdsxyz123@yahoo.com> Mark D. Studebaker <mdsxyz123@yahoo.com>
Based on code written by Ralph Metzler <rjkm@thp.uni-koeln.de> and Based on i2c-voodoo3.c.
Simon Vogl
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
...@@ -195,9 +193,7 @@ static void __exit i2c_savage4_exit(void) ...@@ -195,9 +193,7 @@ static void __exit i2c_savage4_exit(void)
pci_unregister_driver(&savage4_driver); pci_unregister_driver(&savage4_driver);
} }
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, " MODULE_AUTHOR("Alexander Wold <awold@bigfoot.com> "
"Philip Edelbrock <phil@netroedge.com>, "
"Ralph Metzler <rjkm@thp.uni-koeln.de>, "
"and Mark D. Studebaker <mdsxyz123@yahoo.com>"); "and Mark D. Studebaker <mdsxyz123@yahoo.com>");
MODULE_DESCRIPTION("Savage4 I2C/SMBus driver"); MODULE_DESCRIPTION("Savage4 I2C/SMBus driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
......
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* i2c-velleman.c i2c-hw access for Velleman K9000 adapters */ /* i2c-velleman.c i2c-hw access for Velleman K8000 adapters */
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* Copyright (C) 1995-96, 2000 Simon G. Vogl /* Copyright (C) 1995-96, 2000 Simon G. Vogl
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
8233 8233
8233A (0x3147 and 0x3177) 8233A (0x3147 and 0x3177)
8235 8235
8237
Note: we assume there can only be one device, with one SMBus interface. Note: we assume there can only be one device, with one SMBus interface.
*/ */
...@@ -434,6 +435,13 @@ static struct pci_device_id vt596_ids[] = { ...@@ -434,6 +435,13 @@ static struct pci_device_id vt596_ids[] = {
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.driver_data = SMBBA3 .driver_data = SMBBA3
}, },
{
.vendor = PCI_VENDOR_ID_VIA,
.device = PCI_DEVICE_ID_VIA_8237,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.driver_data = SMBBA3
},
{ {
.vendor = PCI_VENDOR_ID_VIA, .vendor = PCI_VENDOR_ID_VIA,
.device = PCI_DEVICE_ID_VIA_8231_4, .device = PCI_DEVICE_ID_VIA_8231_4,
......
...@@ -68,6 +68,17 @@ config SENSORS_LM78 ...@@ -68,6 +68,17 @@ config SENSORS_LM78
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 lm78. will be called lm78.
config SENSORS_LM83
tristate "National Semiconductor LM83"
depends on I2C && EXPERIMENTAL
select I2C_SENSOR
help
If you say yes here you get support for National Semiconductor
LM83 sensor chips.
This driver can also be built as a module. If so, the module
will be called lm83.
config SENSORS_LM85 config SENSORS_LM85
tristate "National Semiconductor LM85 and compatibles" tristate "National Semiconductor LM85 and compatibles"
depends on I2C && EXPERIMENTAL depends on I2C && EXPERIMENTAL
......
...@@ -10,5 +10,6 @@ obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o ...@@ -10,5 +10,6 @@ obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o
obj-$(CONFIG_SENSORS_IT87) += it87.o obj-$(CONFIG_SENSORS_IT87) += it87.o
obj-$(CONFIG_SENSORS_LM75) += lm75.o obj-$(CONFIG_SENSORS_LM75) += lm75.o
obj-$(CONFIG_SENSORS_LM78) += lm78.o obj-$(CONFIG_SENSORS_LM78) += lm78.o
obj-$(CONFIG_SENSORS_LM83) += lm83.o
obj-$(CONFIG_SENSORS_LM85) += lm85.o obj-$(CONFIG_SENSORS_LM85) += lm85.o
obj-$(CONFIG_SENSORS_VIA686A) += via686a.o obj-$(CONFIG_SENSORS_VIA686A) += via686a.o
...@@ -343,7 +343,6 @@ static ssize_t show_temp(struct device *dev, char *buf, int nr) ...@@ -343,7 +343,6 @@ static ssize_t show_temp(struct device *dev, char *buf, int nr)
it87_update_client(client); it87_update_client(client);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr])*100 ); return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr])*100 );
} }
/* more like overshoot temperature */
static ssize_t show_temp_max(struct device *dev, char *buf, int nr) static ssize_t show_temp_max(struct device *dev, char *buf, int nr)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
...@@ -351,7 +350,6 @@ static ssize_t show_temp_max(struct device *dev, char *buf, int nr) ...@@ -351,7 +350,6 @@ static ssize_t show_temp_max(struct device *dev, char *buf, int nr)
it87_update_client(client); it87_update_client(client);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_high[nr])*100); return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_high[nr])*100);
} }
/* more like hysteresis temperature */
static ssize_t show_temp_min(struct device *dev, char *buf, int nr) static ssize_t show_temp_min(struct device *dev, char *buf, int nr)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
...@@ -414,7 +412,6 @@ show_temp_offset(1); ...@@ -414,7 +412,6 @@ show_temp_offset(1);
show_temp_offset(2); show_temp_offset(2);
show_temp_offset(3); show_temp_offset(3);
/* more like overshoot temperature */
static ssize_t show_sensor(struct device *dev, char *buf, int nr) static ssize_t show_sensor(struct device *dev, char *buf, int nr)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
...@@ -563,15 +560,15 @@ show_fan_offset(1); ...@@ -563,15 +560,15 @@ show_fan_offset(1);
show_fan_offset(2); show_fan_offset(2);
show_fan_offset(3); show_fan_offset(3);
/* Alarm */ /* Alarms */
static ssize_t show_alarm(struct device *dev, char *buf) static ssize_t show_alarms(struct device *dev, char *buf)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client); struct it87_data *data = i2c_get_clientdata(client);
it87_update_client(client); it87_update_client(client);
return sprintf(buf,"%d\n", ALARMS_FROM_REG(data->alarms)); return sprintf(buf,"%d\n", ALARMS_FROM_REG(data->alarms));
} }
static DEVICE_ATTR(alarm, S_IRUGO | S_IWUSR, show_alarm, NULL); static DEVICE_ATTR(alarms, S_IRUGO | S_IWUSR, show_alarms, NULL);
/* This function is called when: /* This function is called when:
* it87_driver is inserted (when this module is loaded), for each * it87_driver is inserted (when this module is loaded), for each
...@@ -751,7 +748,7 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -751,7 +748,7 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
device_create_file(&new_client->dev, &dev_attr_fan_div1); device_create_file(&new_client->dev, &dev_attr_fan_div1);
device_create_file(&new_client->dev, &dev_attr_fan_div2); device_create_file(&new_client->dev, &dev_attr_fan_div2);
device_create_file(&new_client->dev, &dev_attr_fan_div3); device_create_file(&new_client->dev, &dev_attr_fan_div3);
device_create_file(&new_client->dev, &dev_attr_alarm); device_create_file(&new_client->dev, &dev_attr_alarms);
return 0; return 0;
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-sensor.h> #include <linux/i2c-sensor.h>
#include "lm75.h"
/* Addresses to scan */ /* Addresses to scan */
...@@ -44,17 +45,6 @@ SENSORS_INSMOD_1(lm75); ...@@ -44,17 +45,6 @@ SENSORS_INSMOD_1(lm75);
#define LM75_REG_TEMP_HYST 0x02 #define LM75_REG_TEMP_HYST 0x02
#define LM75_REG_TEMP_OS 0x03 #define LM75_REG_TEMP_OS 0x03
/* Conversions. Rounding and limit checking is only done on the TO_REG
variants. Note that you should be a bit careful with which arguments
these macros are called: arguments may be evaluated more than once.
Fixing this is just not worth it. */
#define TEMP_FROM_REG(val) ((((val & 0x7fff) >> 7) * 5) | ((val & 0x8000)?-256:0))
#define TEMP_TO_REG(val) (SENSORS_LIMIT((val<0?(0x200+((val)/5))<<7:(((val) + 2) / 5) << 7),0,0xffff))
/* Initial values */
#define LM75_INIT_TEMP_OS 600
#define LM75_INIT_TEMP_HYST 500
/* Each client has this additional data */ /* Each client has this additional data */
struct lm75_data { struct lm75_data {
struct semaphore update_lock; struct semaphore update_lock;
...@@ -87,15 +77,12 @@ static struct i2c_driver lm75_driver = { ...@@ -87,15 +77,12 @@ static struct i2c_driver lm75_driver = {
static int lm75_id = 0; static int lm75_id = 0;
#define show(value) \ #define show(value) \
static ssize_t show_##value(struct device *dev, char *buf) \ static ssize_t show_##value(struct device *dev, char *buf) \
{ \ { \
struct i2c_client *client = to_i2c_client(dev); \ struct i2c_client *client = to_i2c_client(dev); \
struct lm75_data *data = i2c_get_clientdata(client); \ struct lm75_data *data = i2c_get_clientdata(client); \
int temp; \ lm75_update_client(client); \
\ return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->value)); \
lm75_update_client(client); \
temp = TEMP_FROM_REG(data->value); \
return sprintf(buf, "%d\n", temp * 100); \
} }
show(temp_max); show(temp_max);
show(temp_hyst); show(temp_hyst);
...@@ -106,9 +93,8 @@ static ssize_t set_##value(struct device *dev, const char *buf, size_t count) \ ...@@ -106,9 +93,8 @@ static ssize_t set_##value(struct device *dev, const char *buf, size_t count) \
{ \ { \
struct i2c_client *client = to_i2c_client(dev); \ struct i2c_client *client = to_i2c_client(dev); \
struct lm75_data *data = i2c_get_clientdata(client); \ struct lm75_data *data = i2c_get_clientdata(client); \
int temp = simple_strtoul(buf, NULL, 10) / 100; \ int temp = simple_strtoul(buf, NULL, 10); \
\ data->value = LM75_TEMP_TO_REG(temp); \
data->value = TEMP_TO_REG(temp); \
lm75_write_value(client, reg, data->value); \ lm75_write_value(client, reg, data->value); \
return count; \ return count; \
} }
...@@ -116,7 +102,7 @@ set(temp_max, LM75_REG_TEMP_OS); ...@@ -116,7 +102,7 @@ set(temp_max, LM75_REG_TEMP_OS);
set(temp_hyst, LM75_REG_TEMP_HYST); set(temp_hyst, LM75_REG_TEMP_HYST);
static DEVICE_ATTR(temp_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max); static DEVICE_ATTR(temp_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max);
static DEVICE_ATTR(temp_min, S_IWUSR | S_IRUGO, show_temp_hyst, set_temp_hyst); static DEVICE_ATTR(temp_hyst, S_IWUSR | S_IRUGO, show_temp_hyst, set_temp_hyst);
static DEVICE_ATTR(temp_input, S_IRUGO, show_temp_input, NULL); static DEVICE_ATTR(temp_input, S_IRUGO, show_temp_input, NULL);
static int lm75_attach_adapter(struct i2c_adapter *adapter) static int lm75_attach_adapter(struct i2c_adapter *adapter)
...@@ -209,7 +195,7 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -209,7 +195,7 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
/* Register sysfs hooks */ /* Register sysfs hooks */
device_create_file(&new_client->dev, &dev_attr_temp_max); device_create_file(&new_client->dev, &dev_attr_temp_max);
device_create_file(&new_client->dev, &dev_attr_temp_min); device_create_file(&new_client->dev, &dev_attr_temp_hyst);
device_create_file(&new_client->dev, &dev_attr_temp_input); device_create_file(&new_client->dev, &dev_attr_temp_input);
return 0; return 0;
...@@ -258,10 +244,6 @@ static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value) ...@@ -258,10 +244,6 @@ static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value)
static void lm75_init_client(struct i2c_client *client) static void lm75_init_client(struct i2c_client *client)
{ {
/* Initialize the LM75 chip */ /* Initialize the LM75 chip */
lm75_write_value(client, LM75_REG_TEMP_OS,
TEMP_TO_REG(LM75_INIT_TEMP_OS));
lm75_write_value(client, LM75_REG_TEMP_HYST,
TEMP_TO_REG(LM75_INIT_TEMP_HYST));
lm75_write_value(client, LM75_REG_CONF, 0); lm75_write_value(client, LM75_REG_CONF, 0);
} }
......
/*
lm75.h - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (c) 2003 Mark M. Hoffman <mhoffman@lightlink.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
This file contains common code for encoding/decoding LM75 type
temperature readings, which are emulated by many of the chips
we support. As the user is unlikely to load more than one driver
which contains this code, we don't worry about the wasted space.
*/
#include <linux/i2c-sensor.h>
/* straight from the datasheet */
#define LM75_TEMP_MIN (-55000)
#define LM75_TEMP_MAX 125000
/* TEMP: 0.001C/bit (-55C to +125C)
REG: (0.5C/bit, two's complement) << 7 */
static inline u16 LM75_TEMP_TO_REG(int temp)
{
int ntemp = SENSORS_LIMIT(temp, LM75_TEMP_MIN, LM75_TEMP_MAX);
ntemp += (ntemp<0 ? -250 : 250);
return (u16)((ntemp / 500) << 7);
}
static inline int LM75_TEMP_FROM_REG(u16 reg)
{
/* use integer division instead of equivalent right shift to
guarantee arithmetic shift and preserve the sign */
return ((s16)reg / 128) * 500;
}
...@@ -367,7 +367,7 @@ static ssize_t set_temp_hyst(struct device *dev, const char *buf, size_t count) ...@@ -367,7 +367,7 @@ static ssize_t set_temp_hyst(struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(temp_input, S_IRUGO, show_temp, NULL) static DEVICE_ATTR(temp_input, S_IRUGO, show_temp, NULL)
static DEVICE_ATTR(temp_max, S_IRUGO | S_IWUSR, static DEVICE_ATTR(temp_max, S_IRUGO | S_IWUSR,
show_temp_over, set_temp_over) show_temp_over, set_temp_over)
static DEVICE_ATTR(temp_min, S_IRUGO | S_IWUSR, static DEVICE_ATTR(temp_hyst, S_IRUGO | S_IWUSR,
show_temp_hyst, set_temp_hyst) show_temp_hyst, set_temp_hyst)
/* 3 Fans */ /* 3 Fans */
...@@ -674,8 +674,8 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -674,8 +674,8 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
device_create_file(&new_client->dev, &dev_attr_in_min6); device_create_file(&new_client->dev, &dev_attr_in_min6);
device_create_file(&new_client->dev, &dev_attr_in_max6); device_create_file(&new_client->dev, &dev_attr_in_max6);
device_create_file(&new_client->dev, &dev_attr_temp_input); device_create_file(&new_client->dev, &dev_attr_temp_input);
device_create_file(&new_client->dev, &dev_attr_temp_min);
device_create_file(&new_client->dev, &dev_attr_temp_max); device_create_file(&new_client->dev, &dev_attr_temp_max);
device_create_file(&new_client->dev, &dev_attr_temp_hyst);
device_create_file(&new_client->dev, &dev_attr_fan_input1); device_create_file(&new_client->dev, &dev_attr_fan_input1);
device_create_file(&new_client->dev, &dev_attr_fan_min1); device_create_file(&new_client->dev, &dev_attr_fan_min1);
device_create_file(&new_client->dev, &dev_attr_fan_div1); device_create_file(&new_client->dev, &dev_attr_fan_div1);
......
/*
* lm83.c - Part of lm_sensors, Linux kernel modules for hardware
* monitoring
* Copyright (C) 2003 Jean Delvare <khali@linux-fr.org>
*
* Heavily inspired from the lm78, lm75 and adm1021 drivers. The LM83 is
* a sensor chip made by National Semiconductor. It reports up to four
* temperatures (its own plus up to three external ones) with a 1 deg
* resolution and a 3-4 deg accuracy. Complete datasheet can be obtained
* from National's website at:
* http://www.national.com/pf/LM/LM83.html
* Since the datasheet omits to give the chip stepping code, I give it
* here: 0x03 (at register 0xff).
*
* 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/i2c.h>
#include <linux/i2c-sensor.h>
/*
* Addresses to scan
* Address is selected using 2 three-level pins, resulting in 9 possible
* addresses.
*/
static unsigned short normal_i2c[] = { I2C_CLIENT_END };
static unsigned short normal_i2c_range[] = { 0x18, 0x1a, 0x29, 0x2b,
0x4c, 0x4e, I2C_CLIENT_END };
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
/*
* Insmod parameters
*/
SENSORS_INSMOD_1(lm83);
/*
* The LM83 registers
* Manufacturer ID is 0x01 for National Semiconductor.
*/
#define LM83_REG_R_MAN_ID 0xFE
#define LM83_REG_R_CHIP_ID 0xFF
#define LM83_REG_R_CONFIG 0x03
#define LM83_REG_W_CONFIG 0x09
#define LM83_REG_R_STATUS1 0x02
#define LM83_REG_R_STATUS2 0x35
#define LM83_REG_R_LOCAL_TEMP 0x00
#define LM83_REG_R_LOCAL_HIGH 0x05
#define LM83_REG_W_LOCAL_HIGH 0x0B
#define LM83_REG_R_REMOTE1_TEMP 0x30
#define LM83_REG_R_REMOTE1_HIGH 0x38
#define LM83_REG_W_REMOTE1_HIGH 0x50
#define LM83_REG_R_REMOTE2_TEMP 0x01
#define LM83_REG_R_REMOTE2_HIGH 0x07
#define LM83_REG_W_REMOTE2_HIGH 0x0D
#define LM83_REG_R_REMOTE3_TEMP 0x31
#define LM83_REG_R_REMOTE3_HIGH 0x3A
#define LM83_REG_W_REMOTE3_HIGH 0x52
#define LM83_REG_R_TCRIT 0x42
#define LM83_REG_W_TCRIT 0x5A
/*
* Conversions and various macros
* The LM83 uses signed 8-bit values.
*/
#define TEMP_FROM_REG(val) ((val > 127 ? val-256 : val) * 1000)
#define TEMP_TO_REG(val) ((val < 0 ? val+256 : val) / 1000)
static const u8 LM83_REG_R_TEMP[] = {
LM83_REG_R_LOCAL_TEMP,
LM83_REG_R_REMOTE1_TEMP,
LM83_REG_R_REMOTE2_TEMP,
LM83_REG_R_REMOTE3_TEMP
};
static const u8 LM83_REG_R_HIGH[] = {
LM83_REG_R_LOCAL_HIGH,
LM83_REG_R_REMOTE1_HIGH,
LM83_REG_R_REMOTE2_HIGH,
LM83_REG_R_REMOTE3_HIGH
};
static const u8 LM83_REG_W_HIGH[] = {
LM83_REG_W_LOCAL_HIGH,
LM83_REG_W_REMOTE1_HIGH,
LM83_REG_W_REMOTE2_HIGH,
LM83_REG_W_REMOTE3_HIGH
};
/*
* Functions declaration
*/
static int lm83_attach_adapter(struct i2c_adapter *adapter);
static int lm83_detect(struct i2c_adapter *adapter, int address, int kind);
static int lm83_detach_client(struct i2c_client *client);
static void lm83_update_client(struct i2c_client *client);
/*
* Driver data (common to all clients)
*/
static struct i2c_driver lm83_driver = {
.owner = THIS_MODULE,
.name = "lm83",
.id = I2C_DRIVERID_LM83,
.flags = I2C_DF_NOTIFY,
.attach_adapter = lm83_attach_adapter,
.detach_client = lm83_detach_client,
};
/*
* Client data (each client gets its own)
*/
struct lm83_data {
struct semaphore update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
/* registers values */
u8 temp_input[4];
u8 temp_high[4];
u8 temp_crit;
u16 alarms; /* bitvector, combined */
};
/*
* Internal variables
*/
static int lm83_id = 0;
/*
* Sysfs stuff
*/
#define show_temp(suffix, value) \
static ssize_t show_temp_##suffix(struct device *dev, char *buf) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct lm83_data *data = i2c_get_clientdata(client); \
lm83_update_client(client); \
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->value)); \
}
show_temp(input1, temp_input[0]);
show_temp(input2, temp_input[1]);
show_temp(input3, temp_input[2]);
show_temp(input4, temp_input[3]);
show_temp(high1, temp_high[0]);
show_temp(high2, temp_high[1]);
show_temp(high3, temp_high[2]);
show_temp(high4, temp_high[3]);
show_temp(crit, temp_crit);
#define set_temp(suffix, value, reg) \
static ssize_t set_temp_##suffix(struct device *dev, const char *buf, \
size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct lm83_data *data = i2c_get_clientdata(client); \
data->value = TEMP_TO_REG(simple_strtoul(buf, NULL, 10)); \
i2c_smbus_write_byte_data(client, reg, data->value); \
return count; \
}
set_temp(high1, temp_high[0], LM83_REG_W_LOCAL_HIGH);
set_temp(high2, temp_high[1], LM83_REG_W_REMOTE1_HIGH);
set_temp(high3, temp_high[2], LM83_REG_W_REMOTE2_HIGH);
set_temp(high4, temp_high[3], LM83_REG_W_REMOTE3_HIGH);
set_temp(crit, temp_crit, LM83_REG_W_TCRIT);
static ssize_t show_alarms(struct device *dev, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm83_data *data = i2c_get_clientdata(client);
lm83_update_client(client);
return sprintf(buf, "%d\n", data->alarms);
}
static DEVICE_ATTR(temp_input1, S_IRUGO, show_temp_input1, NULL);
static DEVICE_ATTR(temp_input2, S_IRUGO, show_temp_input2, NULL);
static DEVICE_ATTR(temp_input3, S_IRUGO, show_temp_input3, NULL);
static DEVICE_ATTR(temp_input4, S_IRUGO, show_temp_input4, NULL);
static DEVICE_ATTR(temp_max1, S_IWUSR | S_IRUGO, show_temp_high1,
set_temp_high1);
static DEVICE_ATTR(temp_max2, S_IWUSR | S_IRUGO, show_temp_high2,
set_temp_high2);
static DEVICE_ATTR(temp_max3, S_IWUSR | S_IRUGO, show_temp_high3,
set_temp_high3);
static DEVICE_ATTR(temp_max4, S_IWUSR | S_IRUGO, show_temp_high4,
set_temp_high4);
static DEVICE_ATTR(temp_crit, S_IWUSR | S_IRUGO, show_temp_crit,
set_temp_crit);
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
/*
* Real code
*/
static int lm83_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_ADAP_CLASS_SMBUS))
return 0;
return i2c_detect(adapter, &addr_data, lm83_detect);
}
/*
* The following function does more than just detection. If detection
* succeeds, it also registers the new chip.
*/
static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *new_client;
struct lm83_data *data;
int err = 0;
const char *name = "";
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit;
if (!(new_client = kmalloc(sizeof(struct i2c_client) +
sizeof(struct lm83_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
memset(new_client, 0x00, sizeof(struct i2c_client) +
sizeof(struct lm83_data));
/* The LM83-specific data is placed right after the common I2C
* client data. */
data = (struct lm83_data *) (new_client + 1);
i2c_set_clientdata(new_client, data);
new_client->addr = address;
new_client->adapter = adapter;
new_client->driver = &lm83_driver;
new_client->flags = 0;
/* Now we do the detection and identification. A negative kind
* means that the driver was loaded with no force parameter
* (default), so we must both detect and identify the chip
* (actually there is only one possible kind of chip for now, LM83).
* A zero kind means that the driver was loaded with the force
* parameter, the detection step shall be skipped. A positive kind
* means that the driver was loaded with the force parameter and a
* given kind of chip is requested, so both the detection and the
* identification steps are skipped. */
if (kind < 0) { /* detection */
if (((i2c_smbus_read_byte_data(new_client, LM83_REG_R_STATUS1)
& 0xA8) != 0x00) ||
((i2c_smbus_read_byte_data(new_client, LM83_REG_R_STATUS2)
& 0x48) != 0x00) ||
((i2c_smbus_read_byte_data(new_client, LM83_REG_R_CONFIG)
& 0x41) != 0x00)) {
dev_dbg(&client->dev,
"LM83 detection failed at 0x%02x.\n", address);
goto exit_free;
}
}
if (kind <= 0) { /* identification */
u8 man_id, chip_id;
man_id = i2c_smbus_read_byte_data(new_client,
LM83_REG_R_MAN_ID);
chip_id = i2c_smbus_read_byte_data(new_client,
LM83_REG_R_CHIP_ID);
if (man_id == 0x01) { /* National Semiconductor */
if (chip_id == 0x03) {
kind = lm83;
name = "lm83";
}
}
if (kind <= 0) { /* identification failed */
dev_info(&adapter->dev,
"Unsupported chip (man_id=0x%02X, "
"chip_id=0x%02X).\n", man_id, chip_id);
goto exit_free;
}
}
/* We can fill in the remaining client fields */
strlcpy(new_client->name, name, I2C_NAME_SIZE);
new_client->id = lm83_id++;
data->valid = 0;
init_MUTEX(&data->update_lock);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
goto exit_free;
/*
* Initialize the LM83 chip
* (Nothing to do for this one.)
*/
/* Register sysfs hooks */
device_create_file(&new_client->dev, &dev_attr_temp_input1);
device_create_file(&new_client->dev, &dev_attr_temp_input2);
device_create_file(&new_client->dev, &dev_attr_temp_input3);
device_create_file(&new_client->dev, &dev_attr_temp_input4);
device_create_file(&new_client->dev, &dev_attr_temp_max1);
device_create_file(&new_client->dev, &dev_attr_temp_max2);
device_create_file(&new_client->dev, &dev_attr_temp_max3);
device_create_file(&new_client->dev, &dev_attr_temp_max4);
device_create_file(&new_client->dev, &dev_attr_temp_crit);
device_create_file(&new_client->dev, &dev_attr_alarms);
return 0;
exit_free:
kfree(new_client);
exit:
return err;
}
static int lm83_detach_client(struct i2c_client *client)
{
int err;
if ((err = i2c_detach_client(client))) {
dev_err(&client->dev,
"Client deregistration failed, client not detached.\n");
return err;
}
kfree(client);
return 0;
}
static void lm83_update_client(struct i2c_client *client)
{
struct lm83_data *data = i2c_get_clientdata(client);
down(&data->update_lock);
if ((jiffies - data->last_updated > HZ * 2) ||
(jiffies < data->last_updated) ||
!data->valid) {
int nr;
dev_dbg(&client->dev, "Updating lm83 data.\n");
for (nr = 0; nr < 4 ; nr++) {
data->temp_input[nr] =
i2c_smbus_read_byte_data(client,
LM83_REG_R_TEMP[nr]);
data->temp_high[nr] =
i2c_smbus_read_byte_data(client,
LM83_REG_R_HIGH[nr]);
}
data->temp_crit =
i2c_smbus_read_byte_data(client, LM83_REG_R_TCRIT);
data->alarms =
i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS1)
+ (i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS2)
<< 8);
data->last_updated = jiffies;
data->valid = 1;
}
up(&data->update_lock);
}
static int __init sensors_lm83_init(void)
{
return i2c_add_driver(&lm83_driver);
}
static void __exit sensors_lm83_exit(void)
{
i2c_del_driver(&lm83_driver);
}
MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
MODULE_DESCRIPTION("LM83 driver");
MODULE_LICENSE("GPL");
module_init(sensors_lm83_init);
module_exit(sensors_lm83_exit);
...@@ -496,21 +496,19 @@ static ssize_t show_temp(struct device *dev, char *buf, int nr) { ...@@ -496,21 +496,19 @@ static ssize_t show_temp(struct device *dev, char *buf, int nr) {
via686a_update_client(client); via686a_update_client(client);
return sprintf(buf, "%ld\n", TEMP_FROM_REG10(data->temp[nr])*100 ); return sprintf(buf, "%ld\n", TEMP_FROM_REG10(data->temp[nr])*100 );
} }
/* more like overshoot temperature */ static ssize_t show_temp_over(struct device *dev, char *buf, int nr) {
static ssize_t show_temp_max(struct device *dev, char *buf, int nr) {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct via686a_data *data = i2c_get_clientdata(client); struct via686a_data *data = i2c_get_clientdata(client);
via686a_update_client(client); via686a_update_client(client);
return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_over[nr])*100); return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_over[nr])*100);
} }
/* more like hysteresis temperature */ static ssize_t show_temp_hyst(struct device *dev, char *buf, int nr) {
static ssize_t show_temp_min(struct device *dev, char *buf, int nr) {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct via686a_data *data = i2c_get_clientdata(client); struct via686a_data *data = i2c_get_clientdata(client);
via686a_update_client(client); via686a_update_client(client);
return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_hyst[nr])*100); return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_hyst[nr])*100);
} }
static ssize_t set_temp_max(struct device *dev, const char *buf, static ssize_t set_temp_over(struct device *dev, const char *buf,
size_t count, int nr) { size_t count, int nr) {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct via686a_data *data = i2c_get_clientdata(client); struct via686a_data *data = i2c_get_clientdata(client);
...@@ -519,7 +517,7 @@ static ssize_t set_temp_max(struct device *dev, const char *buf, ...@@ -519,7 +517,7 @@ static ssize_t set_temp_max(struct device *dev, const char *buf,
via686a_write_value(client, VIA686A_REG_TEMP_OVER(nr), data->temp_over[nr]); via686a_write_value(client, VIA686A_REG_TEMP_OVER(nr), data->temp_over[nr]);
return count; return count;
} }
static ssize_t set_temp_min(struct device *dev, const char *buf, static ssize_t set_temp_hyst(struct device *dev, const char *buf,
size_t count, int nr) { size_t count, int nr) {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct via686a_data *data = i2c_get_clientdata(client); struct via686a_data *data = i2c_get_clientdata(client);
...@@ -534,30 +532,30 @@ static ssize_t show_temp_##offset (struct device *dev, char *buf) \ ...@@ -534,30 +532,30 @@ static ssize_t show_temp_##offset (struct device *dev, char *buf) \
return show_temp(dev, buf, 0x##offset - 1); \ return show_temp(dev, buf, 0x##offset - 1); \
} \ } \
static ssize_t \ static ssize_t \
show_temp_##offset##_max (struct device *dev, char *buf) \ show_temp_##offset##_over (struct device *dev, char *buf) \
{ \ { \
return show_temp_max(dev, buf, 0x##offset - 1); \ return show_temp_over(dev, buf, 0x##offset - 1); \
} \ } \
static ssize_t \ static ssize_t \
show_temp_##offset##_min (struct device *dev, char *buf) \ show_temp_##offset##_hyst (struct device *dev, char *buf) \
{ \ { \
return show_temp_min(dev, buf, 0x##offset - 1); \ return show_temp_hyst(dev, buf, 0x##offset - 1); \
} \ } \
static ssize_t set_temp_##offset##_max (struct device *dev, \ static ssize_t set_temp_##offset##_over (struct device *dev, \
const char *buf, size_t count) \ const char *buf, size_t count) \
{ \ { \
return set_temp_max(dev, buf, count, 0x##offset - 1); \ return set_temp_over(dev, buf, count, 0x##offset - 1); \
} \ } \
static ssize_t set_temp_##offset##_min (struct device *dev, \ static ssize_t set_temp_##offset##_hyst (struct device *dev, \
const char *buf, size_t count) \ const char *buf, size_t count) \
{ \ { \
return set_temp_min(dev, buf, count, 0x##offset - 1); \ return set_temp_hyst(dev, buf, count, 0x##offset - 1); \
} \ } \
static DEVICE_ATTR(temp_input##offset, S_IRUGO, show_temp_##offset, NULL) \ static DEVICE_ATTR(temp_input##offset, S_IRUGO, show_temp_##offset, NULL) \
static DEVICE_ATTR(temp_max##offset, S_IRUGO | S_IWUSR, \ static DEVICE_ATTR(temp_max##offset, S_IRUGO | S_IWUSR, \
show_temp_##offset##_max, set_temp_##offset##_max) \ show_temp_##offset##_over, set_temp_##offset##_over) \
static DEVICE_ATTR(temp_min##offset, S_IRUGO | S_IWUSR, \ static DEVICE_ATTR(temp_hyst##offset, S_IRUGO | S_IWUSR, \
show_temp_##offset##_min, set_temp_##offset##_min) show_temp_##offset##_hyst, set_temp_##offset##_hyst)
show_temp_offset(1); show_temp_offset(1);
show_temp_offset(2); show_temp_offset(2);
...@@ -637,14 +635,14 @@ static DEVICE_ATTR(fan_div##offset, S_IRUGO | S_IWUSR, \ ...@@ -637,14 +635,14 @@ static DEVICE_ATTR(fan_div##offset, S_IRUGO | S_IWUSR, \
show_fan_offset(1); show_fan_offset(1);
show_fan_offset(2); show_fan_offset(2);
/* Alarm */ /* Alarms */
static ssize_t show_alarm(struct device *dev, char *buf) { static ssize_t show_alarms(struct device *dev, char *buf) {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct via686a_data *data = i2c_get_clientdata(client); struct via686a_data *data = i2c_get_clientdata(client);
via686a_update_client(client); via686a_update_client(client);
return sprintf(buf,"%d\n", ALARMS_FROM_REG(data->alarms)); return sprintf(buf,"%d\n", ALARMS_FROM_REG(data->alarms));
} }
static DEVICE_ATTR(alarm, S_IRUGO | S_IWUSR, show_alarm, NULL); static DEVICE_ATTR(alarms, S_IRUGO | S_IWUSR, show_alarms, NULL);
/* The driver. I choose to use type i2c_driver, as at is identical to both /* The driver. I choose to use type i2c_driver, as at is identical to both
smbus_driver and isa_driver, and clients could be of either kind */ smbus_driver and isa_driver, and clients could be of either kind */
...@@ -760,16 +758,16 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -760,16 +758,16 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
device_create_file(&new_client->dev, &dev_attr_temp_max1); device_create_file(&new_client->dev, &dev_attr_temp_max1);
device_create_file(&new_client->dev, &dev_attr_temp_max2); device_create_file(&new_client->dev, &dev_attr_temp_max2);
device_create_file(&new_client->dev, &dev_attr_temp_max3); device_create_file(&new_client->dev, &dev_attr_temp_max3);
device_create_file(&new_client->dev, &dev_attr_temp_min1); device_create_file(&new_client->dev, &dev_attr_temp_hyst1);
device_create_file(&new_client->dev, &dev_attr_temp_min2); device_create_file(&new_client->dev, &dev_attr_temp_hyst2);
device_create_file(&new_client->dev, &dev_attr_temp_min3); device_create_file(&new_client->dev, &dev_attr_temp_hyst3);
device_create_file(&new_client->dev, &dev_attr_fan_input1); device_create_file(&new_client->dev, &dev_attr_fan_input1);
device_create_file(&new_client->dev, &dev_attr_fan_input2); device_create_file(&new_client->dev, &dev_attr_fan_input2);
device_create_file(&new_client->dev, &dev_attr_fan_min1); device_create_file(&new_client->dev, &dev_attr_fan_min1);
device_create_file(&new_client->dev, &dev_attr_fan_min2); device_create_file(&new_client->dev, &dev_attr_fan_min2);
device_create_file(&new_client->dev, &dev_attr_fan_div1); device_create_file(&new_client->dev, &dev_attr_fan_div1);
device_create_file(&new_client->dev, &dev_attr_fan_div2); device_create_file(&new_client->dev, &dev_attr_fan_div2);
device_create_file(&new_client->dev, &dev_attr_alarm); device_create_file(&new_client->dev, &dev_attr_alarms);
return 0; return 0;
......
...@@ -24,10 +24,11 @@ ...@@ -24,10 +24,11 @@
Supports following chips: Supports following chips:
Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
as99127f 7 3 1? 3 0x30 0x12c3 yes no as99127f 7 3 1? 3 0x31 0x12c3 yes no
asb100 "bach" (type_name = as99127f) 0x30 0x0694 yes no as99127f rev.2 (type_name = 1299127f) 0x31 0x5ca3 yes no
w83781d 7 3 0 3 0x10 0x5ca3 yes yes asb100 "bach" (type_name = as99127f) 0x31 0x0694 yes no
w83627hf 9 3 2 3 0x20 0x5ca3 yes yes(LPC) w83781d 7 3 0 3 0x10-1 0x5ca3 yes yes
w83627hf 9 3 2 3 0x21 0x5ca3 yes yes(LPC)
w83627thf 9 3 2 3 0x90 0x5ca3 no yes(LPC) w83627thf 9 3 2 3 0x90 0x5ca3 no yes(LPC)
w83782d 9 3 2-4 3 0x30 0x5ca3 yes yes w83782d 9 3 2-4 3 0x30 0x5ca3 yes yes
w83783s 5-6 3 2 1-2 0x40 0x5ca3 yes no w83783s 5-6 3 2 1-2 0x40 0x5ca3 yes no
...@@ -207,72 +208,6 @@ DIV_TO_REG(long val, enum chips type) ...@@ -207,72 +208,6 @@ DIV_TO_REG(long val, enum chips type)
return ((u8) i); return ((u8) i);
} }
/* Initial limits */
#define W83781D_INIT_IN_0 (vid == 3500 ? 280 : vid / 10)
#define W83781D_INIT_IN_1 (vid == 3500 ? 280 : vid / 10)
#define W83781D_INIT_IN_2 330
#define W83781D_INIT_IN_3 (((500) * 100) / 168)
#define W83781D_INIT_IN_4 (((1200) * 10) / 38)
#define W83781D_INIT_IN_5 (((-1200) * -604) / 2100)
#define W83781D_INIT_IN_6 (((-500) * -604) / 909)
#define W83781D_INIT_IN_7 (((500) * 100) / 168)
#define W83781D_INIT_IN_8 300
/* Initial limits for 782d/783s negative voltages */
/* Note level shift. Change min/max below if you change these. */
#define W83782D_INIT_IN_5 ((((-1200) + 1491) * 100)/514)
#define W83782D_INIT_IN_6 ((( (-500) + 771) * 100)/314)
#define W83781D_INIT_IN_PERCENTAGE 10
#define W83781D_INIT_IN_MIN(val) (val - val * W83781D_INIT_IN_PERCENTAGE / 100)
#define W83781D_INIT_IN_MAX(val) (val + val * W83781D_INIT_IN_PERCENTAGE / 100)
#define W83781D_INIT_IN_MIN_0 W83781D_INIT_IN_MIN(W83781D_INIT_IN_0)
#define W83781D_INIT_IN_MAX_0 W83781D_INIT_IN_MAX(W83781D_INIT_IN_0)
#define W83781D_INIT_IN_MIN_1 W83781D_INIT_IN_MIN(W83781D_INIT_IN_1)
#define W83781D_INIT_IN_MAX_1 W83781D_INIT_IN_MAX(W83781D_INIT_IN_1)
#define W83781D_INIT_IN_MIN_2 W83781D_INIT_IN_MIN(W83781D_INIT_IN_2)
#define W83781D_INIT_IN_MAX_2 W83781D_INIT_IN_MAX(W83781D_INIT_IN_2)
#define W83781D_INIT_IN_MIN_3 W83781D_INIT_IN_MIN(W83781D_INIT_IN_3)
#define W83781D_INIT_IN_MAX_3 W83781D_INIT_IN_MAX(W83781D_INIT_IN_3)
#define W83781D_INIT_IN_MIN_4 W83781D_INIT_IN_MIN(W83781D_INIT_IN_4)
#define W83781D_INIT_IN_MAX_4 W83781D_INIT_IN_MAX(W83781D_INIT_IN_4)
#define W83781D_INIT_IN_MIN_5 W83781D_INIT_IN_MIN(W83781D_INIT_IN_5)
#define W83781D_INIT_IN_MAX_5 W83781D_INIT_IN_MAX(W83781D_INIT_IN_5)
#define W83781D_INIT_IN_MIN_6 W83781D_INIT_IN_MIN(W83781D_INIT_IN_6)
#define W83781D_INIT_IN_MAX_6 W83781D_INIT_IN_MAX(W83781D_INIT_IN_6)
#define W83781D_INIT_IN_MIN_7 W83781D_INIT_IN_MIN(W83781D_INIT_IN_7)
#define W83781D_INIT_IN_MAX_7 W83781D_INIT_IN_MAX(W83781D_INIT_IN_7)
#define W83781D_INIT_IN_MIN_8 W83781D_INIT_IN_MIN(W83781D_INIT_IN_8)
#define W83781D_INIT_IN_MAX_8 W83781D_INIT_IN_MAX(W83781D_INIT_IN_8)
/* Initial limits for 782d/783s negative voltages */
/* These aren't direct multiples because of level shift */
/* Beware going negative - check */
#define W83782D_INIT_IN_MIN_5_TMP \
(((-1200 * (100 + W83781D_INIT_IN_PERCENTAGE)) + (1491 * 100))/514)
#define W83782D_INIT_IN_MIN_5 \
((W83782D_INIT_IN_MIN_5_TMP > 0) ? W83782D_INIT_IN_MIN_5_TMP : 0)
#define W83782D_INIT_IN_MAX_5 \
(((-1200 * (100 - W83781D_INIT_IN_PERCENTAGE)) + (1491 * 100))/514)
#define W83782D_INIT_IN_MIN_6_TMP \
((( -500 * (100 + W83781D_INIT_IN_PERCENTAGE)) + (771 * 100))/314)
#define W83782D_INIT_IN_MIN_6 \
((W83782D_INIT_IN_MIN_6_TMP > 0) ? W83782D_INIT_IN_MIN_6_TMP : 0)
#define W83782D_INIT_IN_MAX_6 \
((( -500 * (100 - W83781D_INIT_IN_PERCENTAGE)) + (771 * 100))/314)
#define W83781D_INIT_FAN_MIN_1 3000
#define W83781D_INIT_FAN_MIN_2 3000
#define W83781D_INIT_FAN_MIN_3 3000
/* temp = value / 100 */
#define W83781D_INIT_TEMP_OVER 6000
#define W83781D_INIT_TEMP_HYST 12700 /* must be 127 for ALARM to work */
#define W83781D_INIT_TEMP2_OVER 6000
#define W83781D_INIT_TEMP2_HYST 5000
#define W83781D_INIT_TEMP3_OVER 6000
#define W83781D_INIT_TEMP3_HYST 5000
/* There are some complications in a module like this. First off, W83781D chips /* There are some complications in a module like this. First off, W83781D chips
may be both present on the SMBus and the ISA bus, and we have to handle may be both present on the SMBus and the ISA bus, and we have to handle
those cases separately at some places. Second, there might be several those cases separately at some places. Second, there might be several
...@@ -309,11 +244,11 @@ struct w83781d_data { ...@@ -309,11 +244,11 @@ struct w83781d_data {
u8 fan[3]; /* Register value */ u8 fan[3]; /* Register value */
u8 fan_min[3]; /* Register value */ u8 fan_min[3]; /* Register value */
u8 temp; u8 temp;
u8 temp_min; /* Register value */
u8 temp_max; /* Register value */ u8 temp_max; /* Register value */
u8 temp_hyst; /* Register value */
u16 temp_add[2]; /* Register value */ u16 temp_add[2]; /* Register value */
u16 temp_max_add[2]; /* Register value */ u16 temp_max_add[2]; /* Register value */
u16 temp_min_add[2]; /* Register value */ u16 temp_hyst_add[2]; /* Register value */
u8 fan_div[3]; /* Register encoding, shifted right */ u8 fan_div[3]; /* Register encoding, shifted right */
u8 vid; /* Register encoding, combined */ u8 vid; /* Register encoding, combined */
u32 alarms; /* Register encoding, combined */ u32 alarms; /* Register encoding, combined */
...@@ -510,8 +445,8 @@ static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ ...@@ -510,8 +445,8 @@ static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
} \ } \
} }
show_temp_reg(temp); show_temp_reg(temp);
show_temp_reg(temp_min);
show_temp_reg(temp_max); show_temp_reg(temp_max);
show_temp_reg(temp_hyst);
#define store_temp_reg(REG, reg) \ #define store_temp_reg(REG, reg) \
static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \ static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \
...@@ -538,8 +473,8 @@ static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t cou ...@@ -538,8 +473,8 @@ static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t cou
\ \
return count; \ return count; \
} }
store_temp_reg(OVER, min); store_temp_reg(OVER, max);
store_temp_reg(HYST, max); store_temp_reg(HYST, hyst);
#define sysfs_temp_offset(offset) \ #define sysfs_temp_offset(offset) \
static ssize_t \ static ssize_t \
...@@ -562,8 +497,8 @@ static DEVICE_ATTR(temp_##reg##offset, S_IRUGO| S_IWUSR, show_regs_temp_##reg##o ...@@ -562,8 +497,8 @@ static DEVICE_ATTR(temp_##reg##offset, S_IRUGO| S_IWUSR, show_regs_temp_##reg##o
#define sysfs_temp_offsets(offset) \ #define sysfs_temp_offsets(offset) \
sysfs_temp_offset(offset); \ sysfs_temp_offset(offset); \
sysfs_temp_reg_offset(min, offset); \ sysfs_temp_reg_offset(max, offset); \
sysfs_temp_reg_offset(max, offset); sysfs_temp_reg_offset(hyst, offset);
sysfs_temp_offsets(1); sysfs_temp_offsets(1);
sysfs_temp_offsets(2); sysfs_temp_offsets(2);
...@@ -573,7 +508,7 @@ sysfs_temp_offsets(3); ...@@ -573,7 +508,7 @@ sysfs_temp_offsets(3);
do { \ do { \
device_create_file(&client->dev, &dev_attr_temp_input##offset); \ device_create_file(&client->dev, &dev_attr_temp_input##offset); \
device_create_file(&client->dev, &dev_attr_temp_max##offset); \ device_create_file(&client->dev, &dev_attr_temp_max##offset); \
device_create_file(&client->dev, &dev_attr_temp_min##offset); \ device_create_file(&client->dev, &dev_attr_temp_hyst##offset); \
} while (0) } while (0)
static ssize_t static ssize_t
...@@ -1264,7 +1199,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -1264,7 +1199,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
goto ERROR2; goto ERROR2;
} }
/* If Winbond SMBus, check address at 0x48. /* If Winbond SMBus, check address at 0x48.
Asus doesn't support */ Asus doesn't support, except for as99127f rev.2 */
if ((!is_isa) && (((!(val1 & 0x80)) && (val2 == 0xa3)) || if ((!is_isa) && (((!(val1 & 0x80)) && (val2 == 0xa3)) ||
((val1 & 0x80) && (val2 == 0x5c)))) { ((val1 & 0x80) && (val2 == 0x5c)))) {
if (w83781d_read_value if (w83781d_read_value
...@@ -1295,18 +1230,17 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -1295,18 +1230,17 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
goto ERROR2; goto ERROR2;
} }
/* mask off lower bit, not reliable */ val1 = w83781d_read_value(new_client, W83781D_REG_WCHIPID);
val1 = if ((val1 == 0x10 || val1 == 0x11) && vendid == winbond)
w83781d_read_value(new_client, W83781D_REG_WCHIPID) & 0xfe;
if (val1 == 0x10 && vendid == winbond)
kind = w83781d; kind = w83781d;
else if (val1 == 0x30 && vendid == winbond) else if (val1 == 0x30 && vendid == winbond)
kind = w83782d; kind = w83782d;
else if (val1 == 0x40 && vendid == winbond && !is_isa) else if (val1 == 0x40 && vendid == winbond && !is_isa
&& address == 0x2d)
kind = w83783s; kind = w83783s;
else if ((val1 == 0x20 || val1 == 0x90) && vendid == winbond) else if ((val1 == 0x21 || val1 == 0x90) && vendid == winbond)
kind = w83627hf; kind = w83627hf;
else if (val1 == 0x30 && vendid == asus && !is_isa) else if (val1 == 0x31 && !is_isa && address >= 0x28)
kind = as99127f; kind = as99127f;
else if (val1 == 0x60 && vendid == winbond && is_isa) else if (val1 == 0x60 && vendid == winbond && is_isa)
kind = w83697hf; kind = w83697hf;
...@@ -1688,113 +1622,6 @@ w83781d_init_client(struct i2c_client *client) ...@@ -1688,113 +1622,6 @@ w83781d_init_client(struct i2c_client *client)
#endif /* W83781D_RT */ #endif /* W83781D_RT */
if (init) { if (init) {
w83781d_write_value(client, W83781D_REG_IN_MIN(0),
IN_TO_REG(W83781D_INIT_IN_MIN_0));
w83781d_write_value(client, W83781D_REG_IN_MAX(0),
IN_TO_REG(W83781D_INIT_IN_MAX_0));
if (type != w83783s && type != w83697hf) {
w83781d_write_value(client, W83781D_REG_IN_MIN(1),
IN_TO_REG(W83781D_INIT_IN_MIN_1));
w83781d_write_value(client, W83781D_REG_IN_MAX(1),
IN_TO_REG(W83781D_INIT_IN_MAX_1));
}
w83781d_write_value(client, W83781D_REG_IN_MIN(2),
IN_TO_REG(W83781D_INIT_IN_MIN_2));
w83781d_write_value(client, W83781D_REG_IN_MAX(2),
IN_TO_REG(W83781D_INIT_IN_MAX_2));
w83781d_write_value(client, W83781D_REG_IN_MIN(3),
IN_TO_REG(W83781D_INIT_IN_MIN_3));
w83781d_write_value(client, W83781D_REG_IN_MAX(3),
IN_TO_REG(W83781D_INIT_IN_MAX_3));
w83781d_write_value(client, W83781D_REG_IN_MIN(4),
IN_TO_REG(W83781D_INIT_IN_MIN_4));
w83781d_write_value(client, W83781D_REG_IN_MAX(4),
IN_TO_REG(W83781D_INIT_IN_MAX_4));
if (type == w83781d || type == as99127f) {
w83781d_write_value(client, W83781D_REG_IN_MIN(5),
IN_TO_REG(W83781D_INIT_IN_MIN_5));
w83781d_write_value(client, W83781D_REG_IN_MAX(5),
IN_TO_REG(W83781D_INIT_IN_MAX_5));
} else {
w83781d_write_value(client, W83781D_REG_IN_MIN(5),
IN_TO_REG(W83782D_INIT_IN_MIN_5));
w83781d_write_value(client, W83781D_REG_IN_MAX(5),
IN_TO_REG(W83782D_INIT_IN_MAX_5));
}
if (type == w83781d || type == as99127f) {
w83781d_write_value(client, W83781D_REG_IN_MIN(6),
IN_TO_REG(W83781D_INIT_IN_MIN_6));
w83781d_write_value(client, W83781D_REG_IN_MAX(6),
IN_TO_REG(W83781D_INIT_IN_MAX_6));
} else {
w83781d_write_value(client, W83781D_REG_IN_MIN(6),
IN_TO_REG(W83782D_INIT_IN_MIN_6));
w83781d_write_value(client, W83781D_REG_IN_MAX(6),
IN_TO_REG(W83782D_INIT_IN_MAX_6));
}
if ((type == w83782d) || (type == w83627hf) ||
(type == w83697hf)) {
w83781d_write_value(client, W83781D_REG_IN_MIN(7),
IN_TO_REG(W83781D_INIT_IN_MIN_7));
w83781d_write_value(client, W83781D_REG_IN_MAX(7),
IN_TO_REG(W83781D_INIT_IN_MAX_7));
w83781d_write_value(client, W83781D_REG_IN_MIN(8),
IN_TO_REG(W83781D_INIT_IN_MIN_8));
w83781d_write_value(client, W83781D_REG_IN_MAX(8),
IN_TO_REG(W83781D_INIT_IN_MAX_8));
w83781d_write_value(client, W83781D_REG_VBAT,
(w83781d_read_value
(client,
W83781D_REG_VBAT) | 0x01));
}
w83781d_write_value(client, W83781D_REG_FAN_MIN(1),
FAN_TO_REG(W83781D_INIT_FAN_MIN_1, 2));
w83781d_write_value(client, W83781D_REG_FAN_MIN(2),
FAN_TO_REG(W83781D_INIT_FAN_MIN_2, 2));
if (type != w83697hf) {
w83781d_write_value(client, W83781D_REG_FAN_MIN(3),
FAN_TO_REG(W83781D_INIT_FAN_MIN_3,
2));
}
w83781d_write_value(client, W83781D_REG_TEMP_OVER(1),
TEMP_TO_REG(W83781D_INIT_TEMP_OVER));
w83781d_write_value(client, W83781D_REG_TEMP_HYST(1),
TEMP_TO_REG(W83781D_INIT_TEMP_HYST));
if (type == as99127f) {
w83781d_write_value(client, W83781D_REG_TEMP_OVER(2),
AS99127_TEMP_ADD_TO_REG
(W83781D_INIT_TEMP2_OVER));
w83781d_write_value(client, W83781D_REG_TEMP_HYST(2),
AS99127_TEMP_ADD_TO_REG
(W83781D_INIT_TEMP2_HYST));
} else {
w83781d_write_value(client, W83781D_REG_TEMP_OVER(2),
TEMP_ADD_TO_REG
(W83781D_INIT_TEMP2_OVER));
w83781d_write_value(client, W83781D_REG_TEMP_HYST(2),
TEMP_ADD_TO_REG
(W83781D_INIT_TEMP2_HYST));
}
w83781d_write_value(client, W83781D_REG_TEMP2_CONFIG, 0x00);
if (type == as99127f) {
w83781d_write_value(client, W83781D_REG_TEMP_OVER(3),
AS99127_TEMP_ADD_TO_REG
(W83781D_INIT_TEMP3_OVER));
w83781d_write_value(client, W83781D_REG_TEMP_HYST(3),
AS99127_TEMP_ADD_TO_REG
(W83781D_INIT_TEMP3_HYST));
} else if (type != w83783s && type != w83697hf) {
w83781d_write_value(client, W83781D_REG_TEMP_OVER(3),
TEMP_ADD_TO_REG
(W83781D_INIT_TEMP3_OVER));
w83781d_write_value(client, W83781D_REG_TEMP_HYST(3),
TEMP_ADD_TO_REG
(W83781D_INIT_TEMP3_HYST));
}
if (type != w83783s && type != w83697hf) { if (type != w83783s && type != w83697hf) {
w83781d_write_value(client, W83781D_REG_TEMP3_CONFIG, w83781d_write_value(client, W83781D_REG_TEMP3_CONFIG,
0x00); 0x00);
...@@ -1865,15 +1692,15 @@ w83781d_update_client(struct i2c_client *client) ...@@ -1865,15 +1692,15 @@ w83781d_update_client(struct i2c_client *client)
} }
data->temp = w83781d_read_value(client, W83781D_REG_TEMP(1)); data->temp = w83781d_read_value(client, W83781D_REG_TEMP(1));
data->temp_min =
w83781d_read_value(client, W83781D_REG_TEMP_OVER(1));
data->temp_max = data->temp_max =
w83781d_read_value(client, W83781D_REG_TEMP_OVER(1));
data->temp_hyst =
w83781d_read_value(client, W83781D_REG_TEMP_HYST(1)); w83781d_read_value(client, W83781D_REG_TEMP_HYST(1));
data->temp_add[0] = data->temp_add[0] =
w83781d_read_value(client, W83781D_REG_TEMP(2)); w83781d_read_value(client, W83781D_REG_TEMP(2));
data->temp_max_add[0] = data->temp_max_add[0] =
w83781d_read_value(client, W83781D_REG_TEMP_OVER(2)); w83781d_read_value(client, W83781D_REG_TEMP_OVER(2));
data->temp_min_add[0] = data->temp_hyst_add[0] =
w83781d_read_value(client, W83781D_REG_TEMP_HYST(2)); w83781d_read_value(client, W83781D_REG_TEMP_HYST(2));
if (data->type != w83783s && data->type != w83697hf) { if (data->type != w83783s && data->type != w83697hf) {
data->temp_add[1] = data->temp_add[1] =
...@@ -1881,7 +1708,7 @@ w83781d_update_client(struct i2c_client *client) ...@@ -1881,7 +1708,7 @@ w83781d_update_client(struct i2c_client *client)
data->temp_max_add[1] = data->temp_max_add[1] =
w83781d_read_value(client, w83781d_read_value(client,
W83781D_REG_TEMP_OVER(3)); W83781D_REG_TEMP_OVER(3));
data->temp_min_add[1] = data->temp_hyst_add[1] =
w83781d_read_value(client, w83781d_read_value(client,
W83781D_REG_TEMP_HYST(3)); W83781D_REG_TEMP_HYST(3));
} }
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/i2c.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
......
...@@ -153,6 +153,7 @@ ...@@ -153,6 +153,7 @@
#define I2C_DRIVERID_FS451 1037 #define I2C_DRIVERID_FS451 1037
#define I2C_DRIVERID_W83627HF 1038 #define I2C_DRIVERID_W83627HF 1038
#define I2C_DRIVERID_LM85 1039 #define I2C_DRIVERID_LM85 1039
#define I2C_DRIVERID_LM83 1040
/* /*
* ---- Adapter types ---------------------------------------------------- * ---- Adapter types ----------------------------------------------------
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment