Commit 048c3bac authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge gregkh@kernel.bkbits.net:linux/i2c-2.6

into press.kroah.org:/home/greg/linux/BK/i2c-2.6
parents 8ff96da6 6ed5db86
MODULE: i2c-stub
DESCRIPTION:
This module is a very simple fake I2C/SMBus driver. It implements three
types of SMBus commands: write quick, (r/w) byte data, and (r/w) word data.
No hardware is needed nor associated with this module. It will accept write
quick commands to all addresses; it will respond to the other commands (also
to all addresses) by reading from or writing to an array in memory. It will
also spam the kernel logs for every command it handles.
The typical use-case is like this:
1. load this module
2. use i2cset (from lm_sensors project) to pre-load some data
3. load the target sensors chip driver module
4. observe its behavior in the kernel log
CAVEATS:
There are independent arrays for byte/data and word/data commands. Depending
on if/how a target driver mixes them, you'll need to be careful.
If your target driver polls some byte or word waiting for it to change, the
stub could lock it up. Use i2cset to unlock it.
If the hardware for your driver has banked registers (e.g. Winbond sensors
chips) this module will not work well - although it could be extended to
support that pretty easily.
If you spam it hard enough, printk can be lossy. This module really wants
something like relayfs.
...@@ -24,22 +24,24 @@ all clients from it. Remember, a driver structure contains general access ...@@ -24,22 +24,24 @@ 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.
static struct i2c_driver foo_driver = { static struct i2c_driver foo_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "Foo version 2.3 driver", .name = "Foo version 2.3 driver",
.id = I2C_DRIVERID_FOO, /* usually from i2c-id.h */ .id = I2C_DRIVERID_FOO, /* from i2c-id.h, optional */
.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 */
} }
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
use something descriptive here. use something descriptive here.
The id should be a unique ID. The range 0xf000 to 0xffff is reserved for If used, the id should be a unique ID. The range 0xf000 to 0xffff is
local use, and you can use one of those until you start distributing the reserved for local use, and you can use one of those until you start
driver. Before you do that, contact the i2c authors to get your own ID(s). distributing the driver, at which time you should contact the i2c authors
to get your own ID(s). Note that most of the time you don't need an ID
at all so you can just omit it.
Don't worry about the flags field; just put I2C_DF_NOTIFY into it. This Don't worry about the flags field; just put I2C_DF_NOTIFY into it. This
means that your driver will be notified when new adapters are found. means that your driver will be notified when new adapters are found.
......
...@@ -107,14 +107,6 @@ static int wait_for_bb(struct i2c_algo_iic_data *adap) ...@@ -107,14 +107,6 @@ static int wait_for_bb(struct i2c_algo_iic_data *adap)
return(timeout<=0); return(timeout<=0);
} }
/*
* Puts this process to sleep for a period equal to timeout
*/
static inline void iic_sleep(unsigned long timeout)
{
schedule_timeout( timeout * HZ);
}
/* After we issue a transaction on the IIC bus, this function /* After we issue a transaction on the IIC bus, this function
* is called. It puts this process to sleep until we get an interrupt from * is called. It puts this process to sleep until we get an interrupt from
* from the controller telling us that the transaction we requested in complete. * from the controller telling us that the transaction we requested in complete.
......
...@@ -376,6 +376,19 @@ config I2C_SIS96X ...@@ -376,6 +376,19 @@ config I2C_SIS96X
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-sis96x. will be called i2c-sis96x.
config I2C_STUB
tristate "I2C/SMBus Test Stub"
depends on I2C && EXPERIMENTAL && 'm'
default 'n'
help
This module may be useful to developers of SMBus client drivers,
especially for certain kinds of sensor chips.
If you do build this module, be sure to read the notes and warnings
in Documentation/i2c/i2c-stub.
If you don't know what to do here, definitely say N.
config I2C_VIA config I2C_VIA
tristate "VIA 82C586B" tristate "VIA 82C586B"
depends on I2C && PCI && EXPERIMENTAL depends on I2C && PCI && EXPERIMENTAL
......
...@@ -30,6 +30,7 @@ obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o ...@@ -30,6 +30,7 @@ obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o
obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o
obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o
obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o
obj-$(CONFIG_I2C_STUB) += i2c-stub.o
obj-$(CONFIG_I2C_VIA) += i2c-via.o obj-$(CONFIG_I2C_VIA) += i2c-via.o
obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o
obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o
......
...@@ -496,6 +496,8 @@ static struct pci_device_id ali1535_ids[] = { ...@@ -496,6 +496,8 @@ static struct pci_device_id ali1535_ids[] = {
{ }, { },
}; };
MODULE_DEVICE_TABLE (pci, ali1535_ids);
static int __devinit ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id) static int __devinit ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id)
{ {
if (ali1535_setup(dev)) { if (ali1535_setup(dev)) {
......
...@@ -394,6 +394,8 @@ static struct pci_device_id __devinitdata ali1563_id_table[] = { ...@@ -394,6 +394,8 @@ static struct pci_device_id __devinitdata ali1563_id_table[] = {
{}, {},
}; };
MODULE_DEVICE_TABLE (pci, ali1563_id_table);
static struct pci_driver ali1563_pci_driver = { static struct pci_driver ali1563_pci_driver = {
.name = "ali1563_i2c", .name = "ali1563_i2c",
.id_table = ali1563_id_table, .id_table = ali1563_id_table,
......
...@@ -486,6 +486,8 @@ static struct pci_device_id ali15x3_ids[] = { ...@@ -486,6 +486,8 @@ static struct pci_device_id ali15x3_ids[] = {
{ 0, } { 0, }
}; };
MODULE_DEVICE_TABLE (pci, ali15x3_ids);
static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id) static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id)
{ {
if (ali15x3_setup(dev)) { if (ali15x3_setup(dev)) {
......
...@@ -320,6 +320,8 @@ static struct pci_device_id amd756_ids[] = { ...@@ -320,6 +320,8 @@ static struct pci_device_id amd756_ids[] = {
{ 0, } { 0, }
}; };
MODULE_DEVICE_TABLE (pci, 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)
{ {
......
...@@ -336,6 +336,8 @@ static struct pci_device_id amd8111_ids[] = { ...@@ -336,6 +336,8 @@ static struct pci_device_id amd8111_ids[] = {
{ 0, } { 0, }
}; };
MODULE_DEVICE_TABLE (pci, amd8111_ids);
static int __devinit amd8111_probe(struct pci_dev *dev, const struct pci_device_id *id) static int __devinit amd8111_probe(struct pci_dev *dev, const struct pci_device_id *id)
{ {
struct amd_smbus *smbus; struct amd_smbus *smbus;
......
...@@ -120,6 +120,8 @@ static struct pci_device_id hydra_ids[] = { ...@@ -120,6 +120,8 @@ static struct pci_device_id hydra_ids[] = {
{ 0, } { 0, }
}; };
MODULE_DEVICE_TABLE (pci, hydra_ids);
static int __devinit hydra_probe(struct pci_dev *dev, static int __devinit hydra_probe(struct pci_dev *dev,
const struct pci_device_id *id) const struct pci_device_id *id)
{ {
......
...@@ -599,6 +599,8 @@ static struct pci_device_id i801_ids[] = { ...@@ -599,6 +599,8 @@ static struct pci_device_id i801_ids[] = {
{ 0, } { 0, }
}; };
MODULE_DEVICE_TABLE (pci, i801_ids);
static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id) static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
{ {
......
...@@ -70,7 +70,7 @@ ...@@ -70,7 +70,7 @@
#define CYCLE_DELAY 10 #define CYCLE_DELAY 10
#define TIMEOUT (HZ / 2) #define TIMEOUT (HZ / 2)
static void *ioaddr; static void __iomem *ioaddr;
/* The i810 GPIO registers have individual masks for each bit /* The i810 GPIO registers have individual masks for each bit
so we never have to read before writing. Nice. */ so we never have to read before writing. Nice. */
...@@ -201,6 +201,8 @@ static struct pci_device_id i810_ids[] __devinitdata = { ...@@ -201,6 +201,8 @@ static struct pci_device_id i810_ids[] __devinitdata = {
{ 0, }, { 0, },
}; };
MODULE_DEVICE_TABLE (pci, i810_ids);
static int __devinit i810_probe(struct pci_dev *dev, const struct pci_device_id *id) static int __devinit i810_probe(struct pci_dev *dev, const struct pci_device_id *id)
{ {
int retval; int retval;
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <asm/ocp.h> #include <asm/ocp.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/delay.h>
#define MPC_I2C_ADDR 0x00 #define MPC_I2C_ADDR 0x00
#define MPC_I2C_FDR 0x04 #define MPC_I2C_FDR 0x04
...@@ -91,9 +92,9 @@ static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing) ...@@ -91,9 +92,9 @@ static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
x = readb(i2c->base + MPC_I2C_SR); x = readb(i2c->base + MPC_I2C_SR);
writeb(0, i2c->base + MPC_I2C_SR); writeb(0, i2c->base + MPC_I2C_SR);
} else { } else {
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&i2c->queue, &wait); add_wait_queue(&i2c->queue, &wait);
while (!(i2c->interrupt & CSR_MIF)) { while (!(i2c->interrupt & CSR_MIF)) {
set_current_state(TASK_INTERRUPTIBLE);
if (signal_pending(current)) { if (signal_pending(current)) {
pr_debug("I2C: Interrupted\n"); pr_debug("I2C: Interrupted\n");
result = -EINTR; result = -EINTR;
...@@ -104,9 +105,9 @@ static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing) ...@@ -104,9 +105,9 @@ static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
result = -EIO; result = -EIO;
break; break;
} }
schedule_timeout(timeout); msleep_interruptible(jiffies_to_msecs(timeout));
} }
current->state = TASK_RUNNING; set_current_state(TASK_RUNNING);
remove_wait_queue(&i2c->queue, &wait); remove_wait_queue(&i2c->queue, &wait);
x = i2c->interrupt; x = i2c->interrupt;
i2c->interrupt = 0; i2c->interrupt = 0;
......
...@@ -298,6 +298,9 @@ static struct pci_device_id nforce2_ids[] = { ...@@ -298,6 +298,9 @@ static struct pci_device_id nforce2_ids[] = {
}; };
MODULE_DEVICE_TABLE (pci, nforce2_ids);
static int __devinit nforce2_probe_smb (struct pci_dev *dev, int reg, static int __devinit nforce2_probe_smb (struct pci_dev *dev, int reg,
struct nforce2_smbus *smbus, char *name) struct nforce2_smbus *smbus, char *name)
{ {
......
...@@ -459,6 +459,8 @@ static struct pci_device_id piix4_ids[] = { ...@@ -459,6 +459,8 @@ static struct pci_device_id piix4_ids[] = {
{ 0, } { 0, }
}; };
MODULE_DEVICE_TABLE (pci, piix4_ids);
static int __devinit piix4_probe(struct pci_dev *dev, static int __devinit piix4_probe(struct pci_dev *dev,
const struct pci_device_id *id) const struct pci_device_id *id)
{ {
......
...@@ -68,7 +68,7 @@ ...@@ -68,7 +68,7 @@
#define MAX_BUSSES 2 #define MAX_BUSSES 2
struct s_i2c_bus { struct s_i2c_bus {
void *mmvga; void __iomem *mmvga;
int i2c_reg; int i2c_reg;
int adap_ok; int adap_ok;
struct i2c_adapter adap; struct i2c_adapter adap;
...@@ -76,7 +76,7 @@ struct s_i2c_bus { ...@@ -76,7 +76,7 @@ struct s_i2c_bus {
}; };
struct s_i2c_chip { struct s_i2c_chip {
void *mmio; void __iomem *mmio;
struct s_i2c_bus i2c_bus[MAX_BUSSES]; struct s_i2c_bus i2c_bus[MAX_BUSSES];
}; };
...@@ -181,7 +181,7 @@ static int bit_s3via_getsda(void *bus) ...@@ -181,7 +181,7 @@ static int bit_s3via_getsda(void *bus)
/* /*
* adapter initialisation * adapter initialisation
*/ */
static int i2c_register_bus(struct pci_dev *dev, struct s_i2c_bus *p, u8 *mmvga, u32 i2c_reg) static int i2c_register_bus(struct pci_dev *dev, struct s_i2c_bus *p, void __iomem *mmvga, u32 i2c_reg)
{ {
int ret; int ret;
p->adap.owner = THIS_MODULE; p->adap.owner = THIS_MODULE;
...@@ -313,6 +313,8 @@ static struct pci_device_id prosavage_pci_tbl[] = { ...@@ -313,6 +313,8 @@ static struct pci_device_id prosavage_pci_tbl[] = {
{ 0, }, { 0, },
}; };
MODULE_DEVICE_TABLE (pci, prosavage_pci_tbl);
static struct pci_driver prosavage_driver = { static struct pci_driver prosavage_driver = {
.name = "prosavage_smbus", .name = "prosavage_smbus",
.id_table = prosavage_pci_tbl, .id_table = prosavage_pci_tbl,
......
...@@ -73,7 +73,7 @@ ...@@ -73,7 +73,7 @@
#define TIMEOUT (HZ / 2) #define TIMEOUT (HZ / 2)
static void *ioaddr; static void __iomem *ioaddr;
/* The sav GPIO registers don't have individual masks for each bit /* The sav GPIO registers don't have individual masks for each bit
so we always have to read before writing. */ so we always have to read before writing. */
...@@ -157,6 +157,8 @@ static struct pci_device_id savage4_ids[] __devinitdata = { ...@@ -157,6 +157,8 @@ static struct pci_device_id savage4_ids[] __devinitdata = {
{ 0, } { 0, }
}; };
MODULE_DEVICE_TABLE (pci, savage4_ids);
static int __devinit savage4_probe(struct pci_dev *dev, const struct pci_device_id *id) static int __devinit savage4_probe(struct pci_dev *dev, const struct pci_device_id *id)
{ {
int retval; int retval;
......
...@@ -371,6 +371,8 @@ static struct pci_device_id sis5595_ids[] __devinitdata = { ...@@ -371,6 +371,8 @@ static struct pci_device_id sis5595_ids[] __devinitdata = {
{ 0, } { 0, }
}; };
MODULE_DEVICE_TABLE (pci, sis5595_ids);
static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_id *id) static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_id *id)
{ {
if (sis5595_setup(dev)) { if (sis5595_setup(dev)) {
......
...@@ -468,6 +468,8 @@ static struct pci_device_id sis630_ids[] __devinitdata = { ...@@ -468,6 +468,8 @@ static struct pci_device_id sis630_ids[] __devinitdata = {
{ 0, } { 0, }
}; };
MODULE_DEVICE_TABLE (pci, sis630_ids);
static int __devinit sis630_probe(struct pci_dev *dev, const struct pci_device_id *id) static int __devinit sis630_probe(struct pci_dev *dev, const struct pci_device_id *id)
{ {
if (sis630_setup(dev)) { if (sis630_setup(dev)) {
......
...@@ -278,6 +278,8 @@ static struct pci_device_id sis96x_ids[] = { ...@@ -278,6 +278,8 @@ static struct pci_device_id sis96x_ids[] = {
{ 0, } { 0, }
}; };
MODULE_DEVICE_TABLE (pci, sis96x_ids);
static int __devinit sis96x_probe(struct pci_dev *dev, static int __devinit sis96x_probe(struct pci_dev *dev,
const struct pci_device_id *id) const struct pci_device_id *id)
{ {
......
/*
i2c-stub.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (c) 2004 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.
*/
#define DEBUG 1
#include <linux/config.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/i2c.h>
static u8 stub_bytes[256];
static u16 stub_words[256];
/* Return -1 on error. */
static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
char read_write, u8 command, int size, union i2c_smbus_data * data)
{
s32 ret;
switch (size) {
case I2C_SMBUS_QUICK:
dev_dbg(&adap->dev, "smbus quick - addr 0x%02x\n", addr);
ret = 0;
break;
case I2C_SMBUS_BYTE_DATA:
if (read_write == I2C_SMBUS_WRITE) {
stub_bytes[command] = data->byte;
dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, "
"wrote 0x%02x at 0x%02x.\n",
addr, data->byte, command);
} else {
data->byte = stub_bytes[command];
dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, "
"read 0x%02x at 0x%02x.\n",
addr, data->byte, command);
}
ret = 0;
break;
case I2C_SMBUS_WORD_DATA:
if (read_write == I2C_SMBUS_WRITE) {
stub_words[command] = data->word;
dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, "
"wrote 0x%04x at 0x%02x.\n",
addr, data->word, command);
} else {
data->word = stub_words[command];
dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, "
"read 0x%04x at 0x%02x.\n",
addr, data->word, command);
}
ret = 0;
break;
default:
dev_dbg(&adap->dev, "Unsupported I2C/SMBus command\n");
ret = -1;
break;
} /* switch (size) */
return ret;
}
static u32 stub_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA;
}
static struct i2c_algorithm smbus_algorithm = {
.name = "Non-I2C SMBus adapter",
.id = I2C_ALGO_SMBUS,
.functionality = stub_func,
.smbus_xfer = stub_xfer,
};
static struct i2c_adapter stub_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.algo = &smbus_algorithm,
.name = "SMBus stub driver",
};
static int __init i2c_stub_init(void)
{
printk(KERN_INFO "i2c-stub loaded\n");
return i2c_add_adapter(&stub_adapter);
}
static void __exit i2c_stub_exit(void)
{
i2c_del_adapter(&stub_adapter);
}
MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
MODULE_DESCRIPTION("I2C stub driver");
MODULE_LICENSE("GPL");
module_init(i2c_stub_init);
module_exit(i2c_stub_exit);
...@@ -99,6 +99,8 @@ static struct pci_device_id vt586b_ids[] __devinitdata = { ...@@ -99,6 +99,8 @@ static struct pci_device_id vt586b_ids[] __devinitdata = {
{ 0, } { 0, }
}; };
MODULE_DEVICE_TABLE (pci, vt586b_ids);
static int __devinit vt586b_probe(struct pci_dev *dev, const struct pci_device_id *id) static int __devinit vt586b_probe(struct pci_dev *dev, const struct pci_device_id *id)
{ {
u16 base; u16 base;
......
...@@ -454,6 +454,8 @@ static struct pci_device_id vt596_ids[] = { ...@@ -454,6 +454,8 @@ static struct pci_device_id vt596_ids[] = {
{ 0, } { 0, }
}; };
MODULE_DEVICE_TABLE (pci, vt596_ids);
static struct pci_driver vt596_driver = { static struct pci_driver vt596_driver = {
.name = "vt596_smbus", .name = "vt596_smbus",
.id_table = vt596_ids, .id_table = vt596_ids,
......
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
#define TIMEOUT (HZ / 2) #define TIMEOUT (HZ / 2)
static void *ioaddr; static void __iomem *ioaddr;
/* The voo GPIO registers don't have individual masks for each bit /* The voo GPIO registers don't have individual masks for each bit
so we always have to read before writing. */ so we always have to read before writing. */
...@@ -195,6 +195,8 @@ static struct pci_device_id voodoo3_ids[] __devinitdata = { ...@@ -195,6 +195,8 @@ static struct pci_device_id voodoo3_ids[] __devinitdata = {
{ 0, } { 0, }
}; };
MODULE_DEVICE_TABLE (pci, voodoo3_ids);
static int __devinit voodoo3_probe(struct pci_dev *dev, const struct pci_device_id *id) static int __devinit voodoo3_probe(struct pci_dev *dev, const struct pci_device_id *id)
{ {
int retval; int retval;
......
...@@ -148,7 +148,7 @@ static struct i2c_driver adm1021_driver = { ...@@ -148,7 +148,7 @@ static struct i2c_driver adm1021_driver = {
.detach_client = adm1021_detach_client, .detach_client = adm1021_detach_client,
}; };
static int adm1021_id = 0; static int adm1021_id;
#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) \
......
...@@ -153,7 +153,7 @@ struct adm1025_data { ...@@ -153,7 +153,7 @@ struct adm1025_data {
* Internal variables * Internal variables
*/ */
static int adm1025_id = 0; static int adm1025_id;
/* /*
* Sysfs stuff * Sysfs stuff
...@@ -212,8 +212,8 @@ static ssize_t set_in##offset##_min(struct device *dev, const char *buf, \ ...@@ -212,8 +212,8 @@ static ssize_t set_in##offset##_min(struct device *dev, const char *buf, \
{ \ { \
struct i2c_client *client = to_i2c_client(dev); \ struct i2c_client *client = to_i2c_client(dev); \
struct adm1025_data *data = i2c_get_clientdata(client); \ struct adm1025_data *data = i2c_get_clientdata(client); \
data->in_min[offset] = IN_TO_REG(simple_strtol(buf, NULL, 10), \ long val = simple_strtol(buf, NULL, 10); \
in_scale[offset]); \ data->in_min[offset] = IN_TO_REG(val, in_scale[offset]); \
i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MIN(offset), \ i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MIN(offset), \
data->in_min[offset]); \ data->in_min[offset]); \
return count; \ return count; \
...@@ -223,8 +223,8 @@ static ssize_t set_in##offset##_max(struct device *dev, const char *buf, \ ...@@ -223,8 +223,8 @@ static ssize_t set_in##offset##_max(struct device *dev, const char *buf, \
{ \ { \
struct i2c_client *client = to_i2c_client(dev); \ struct i2c_client *client = to_i2c_client(dev); \
struct adm1025_data *data = i2c_get_clientdata(client); \ struct adm1025_data *data = i2c_get_clientdata(client); \
data->in_max[offset] = IN_TO_REG(simple_strtol(buf, NULL, 10), \ long val = simple_strtol(buf, NULL, 10); \
in_scale[offset]); \ data->in_max[offset] = IN_TO_REG(val, in_scale[offset]); \
i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MAX(offset), \ i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MAX(offset), \
data->in_max[offset]); \ data->in_max[offset]); \
return count; \ return count; \
...@@ -246,7 +246,8 @@ static ssize_t set_temp##offset##_min(struct device *dev, const char *buf, \ ...@@ -246,7 +246,8 @@ static ssize_t set_temp##offset##_min(struct device *dev, const char *buf, \
{ \ { \
struct i2c_client *client = to_i2c_client(dev); \ struct i2c_client *client = to_i2c_client(dev); \
struct adm1025_data *data = i2c_get_clientdata(client); \ struct adm1025_data *data = i2c_get_clientdata(client); \
data->temp_min[offset-1] = TEMP_TO_REG(simple_strtol(buf, NULL, 10)); \ long val = simple_strtol(buf, NULL, 10); \
data->temp_min[offset-1] = TEMP_TO_REG(val); \
i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_LOW(offset-1), \ i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_LOW(offset-1), \
data->temp_min[offset-1]); \ data->temp_min[offset-1]); \
return count; \ return count; \
...@@ -256,7 +257,8 @@ static ssize_t set_temp##offset##_max(struct device *dev, const char *buf, \ ...@@ -256,7 +257,8 @@ static ssize_t set_temp##offset##_max(struct device *dev, const char *buf, \
{ \ { \
struct i2c_client *client = to_i2c_client(dev); \ struct i2c_client *client = to_i2c_client(dev); \
struct adm1025_data *data = i2c_get_clientdata(client); \ struct adm1025_data *data = i2c_get_clientdata(client); \
data->temp_max[offset-1] = TEMP_TO_REG(simple_strtol(buf, NULL, 10)); \ long val = simple_strtol(buf, NULL, 10); \
data->temp_max[offset-1] = TEMP_TO_REG(val); \
i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_HIGH(offset-1), \ i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_HIGH(offset-1), \
data->temp_max[offset-1]); \ data->temp_max[offset-1]); \
return count; \ return count; \
......
...@@ -96,7 +96,7 @@ static struct i2c_driver ds1621_driver = { ...@@ -96,7 +96,7 @@ static struct i2c_driver ds1621_driver = {
.detach_client = ds1621_detach_client, .detach_client = ds1621_detach_client,
}; };
static int ds1621_id = 0; static int ds1621_id;
/* All registers are word-sized, except for the configuration register. /* All registers are word-sized, except for the configuration register.
DS1621 uses a high-byte first convention, which is exactly opposite to DS1621 uses a high-byte first convention, which is exactly opposite to
......
...@@ -86,7 +86,7 @@ static struct i2c_driver eeprom_driver = { ...@@ -86,7 +86,7 @@ static struct i2c_driver eeprom_driver = {
.detach_client = eeprom_detach_client, .detach_client = eeprom_detach_client,
}; };
static int eeprom_id = 0; static int eeprom_id;
static void eeprom_update_client(struct i2c_client *client, u8 slice) static void eeprom_update_client(struct i2c_client *client, u8 slice)
{ {
......
...@@ -156,7 +156,7 @@ struct fscher_data { ...@@ -156,7 +156,7 @@ struct fscher_data {
* Internal variables * Internal variables
*/ */
static int fscher_id = 0; static int fscher_id;
/* /*
* Sysfs stuff * Sysfs stuff
......
...@@ -164,7 +164,7 @@ static struct i2c_driver gl518_driver = { ...@@ -164,7 +164,7 @@ static struct i2c_driver gl518_driver = {
* Internal variables * Internal variables
*/ */
static int gl518_id = 0; static int gl518_id;
/* /*
* Sysfs stuff * Sysfs stuff
...@@ -217,7 +217,8 @@ static ssize_t set_##suffix(struct device *dev, const char *buf, \ ...@@ -217,7 +217,8 @@ static ssize_t set_##suffix(struct device *dev, const char *buf, \
{ \ { \
struct i2c_client *client = to_i2c_client(dev); \ struct i2c_client *client = to_i2c_client(dev); \
struct gl518_data *data = i2c_get_clientdata(client); \ struct gl518_data *data = i2c_get_clientdata(client); \
data->value = type##_TO_REG(simple_strtol(buf, NULL, 10)); \ long val = simple_strtol(buf, NULL, 10); \
data->value = type##_TO_REG(val); \
gl518_write_value(client, reg, data->value); \ gl518_write_value(client, reg, data->value); \
return count; \ return count; \
} }
...@@ -229,7 +230,8 @@ static ssize_t set_##suffix(struct device *dev, const char *buf, \ ...@@ -229,7 +230,8 @@ static ssize_t set_##suffix(struct device *dev, const char *buf, \
struct i2c_client *client = to_i2c_client(dev); \ struct i2c_client *client = to_i2c_client(dev); \
struct gl518_data *data = i2c_get_clientdata(client); \ struct gl518_data *data = i2c_get_clientdata(client); \
int regvalue = gl518_read_value(client, reg); \ int regvalue = gl518_read_value(client, reg); \
data->value = type##_TO_REG(simple_strtoul(buf, NULL, 10)); \ unsigned long val = simple_strtoul(buf, NULL, 10); \
data->value = type##_TO_REG(val); \
regvalue = (regvalue & ~mask) | (data->value << shift); \ regvalue = (regvalue & ~mask) | (data->value << shift); \
gl518_write_value(client, reg, regvalue); \ gl518_write_value(client, reg, regvalue); \
return count; \ return count; \
......
...@@ -226,7 +226,7 @@ static struct i2c_driver it87_driver = { ...@@ -226,7 +226,7 @@ static struct i2c_driver it87_driver = {
.detach_client = it87_detach_client, .detach_client = it87_detach_client,
}; };
static int it87_id = 0; static int it87_id;
static ssize_t show_in(struct device *dev, char *buf, int nr) static ssize_t show_in(struct device *dev, char *buf, int nr)
{ {
......
...@@ -74,7 +74,7 @@ static struct i2c_driver lm75_driver = { ...@@ -74,7 +74,7 @@ static struct i2c_driver lm75_driver = {
.detach_client = lm75_detach_client, .detach_client = lm75_detach_client,
}; };
static int lm75_id = 0; static int lm75_id;
#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) \
......
...@@ -83,7 +83,7 @@ static struct i2c_driver lm77_driver = { ...@@ -83,7 +83,7 @@ static struct i2c_driver lm77_driver = {
.detach_client = lm77_detach_client, .detach_client = lm77_detach_client,
}; };
static int lm77_id = 0; static int lm77_id;
/* straight from the datasheet */ /* straight from the datasheet */
#define LM77_TEMP_MIN (-55000) #define LM77_TEMP_MIN (-55000)
......
...@@ -692,26 +692,12 @@ static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value) ...@@ -692,26 +692,12 @@ static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value)
/* Called when we have found a new LM78. It should set limits, etc. */ /* Called when we have found a new LM78. It should set limits, etc. */
static void lm78_init_client(struct i2c_client *client) static void lm78_init_client(struct i2c_client *client)
{ {
struct lm78_data *data = i2c_get_clientdata(client); u8 config = lm78_read_value(client, LM78_REG_CONFIG);
int vid;
/* Reset all except Watchdog values and last conversion values
This sets fan-divs to 2, among others */
lm78_write_value(client, LM78_REG_CONFIG, 0x80);
vid = lm78_read_value(client, LM78_REG_VID_FANDIV) & 0x0f;
if (data->type == lm79)
vid |=
(lm78_read_value(client, LM78_REG_CHIPID) & 0x01) << 4;
else
vid |= 0x10;
vid = VID_FROM_REG(vid);
/* Start monitoring */ /* Start monitoring */
lm78_write_value(client, LM78_REG_CONFIG, if (!(config & 0x01))
(lm78_read_value(client, LM78_REG_CONFIG) & 0xf7) lm78_write_value(client, LM78_REG_CONFIG,
| 0x01); (config & 0xf7) | 0x01);
} }
static struct lm78_data *lm78_update_device(struct device *dev) static struct lm78_data *lm78_update_device(struct device *dev)
......
...@@ -145,7 +145,7 @@ static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value); ...@@ -145,7 +145,7 @@ static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value);
* Internal variables * Internal variables
*/ */
static int lm80_id = 0; static int lm80_id;
/* /*
* Driver data (common to all clients) * Driver data (common to all clients)
...@@ -262,14 +262,15 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, ...@@ -262,14 +262,15 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct lm80_data *data = i2c_get_clientdata(client); struct lm80_data *data = i2c_get_clientdata(client);
unsigned long min; unsigned long min, val;
u8 reg; u8 reg;
/* Save fan_min */ /* Save fan_min */
min = FAN_FROM_REG(data->fan_min[nr], min = FAN_FROM_REG(data->fan_min[nr],
DIV_FROM_REG(data->fan_div[nr])); DIV_FROM_REG(data->fan_div[nr]));
data->fan_div[nr] = DIV_TO_REG(simple_strtoul(buf, NULL, 10)); val = simple_strtoul(buf, NULL, 10);
data->fan_div[nr] = DIV_TO_REG(val);
reg = (lm80_read_value(client, LM80_REG_FANDIV) & ~(3 << (2 * (nr + 1)))) reg = (lm80_read_value(client, LM80_REG_FANDIV) & ~(3 << (2 * (nr + 1))))
| (data->fan_div[nr] << (2 * (nr + 1))); | (data->fan_div[nr] << (2 * (nr + 1)));
......
...@@ -152,7 +152,7 @@ struct lm83_data { ...@@ -152,7 +152,7 @@ struct lm83_data {
* Internal variables * Internal variables
*/ */
static int lm83_id = 0; static int lm83_id;
/* /*
* Sysfs stuff * Sysfs stuff
...@@ -180,7 +180,8 @@ static ssize_t set_temp_##suffix(struct device *dev, const char *buf, \ ...@@ -180,7 +180,8 @@ static ssize_t set_temp_##suffix(struct device *dev, const char *buf, \
{ \ { \
struct i2c_client *client = to_i2c_client(dev); \ struct i2c_client *client = to_i2c_client(dev); \
struct lm83_data *data = i2c_get_clientdata(client); \ struct lm83_data *data = i2c_get_clientdata(client); \
data->value = TEMP_TO_REG(simple_strtol(buf, NULL, 10)); \ long val = simple_strtol(buf, NULL, 10); \
data->value = TEMP_TO_REG(val); \
i2c_smbus_write_byte_data(client, reg, data->value); \ i2c_smbus_write_byte_data(client, reg, data->value); \
return count; \ return count; \
} }
......
...@@ -405,7 +405,7 @@ static struct i2c_driver lm85_driver = { ...@@ -405,7 +405,7 @@ static struct i2c_driver lm85_driver = {
}; };
/* Unique ID assigned to each LM85 detected */ /* Unique ID assigned to each LM85 detected */
static int lm85_id = 0; static int lm85_id;
/* 4 Fans */ /* 4 Fans */
...@@ -707,6 +707,8 @@ show_temp_reg(3); ...@@ -707,6 +707,8 @@ show_temp_reg(3);
int lm85_attach_adapter(struct i2c_adapter *adapter) int lm85_attach_adapter(struct i2c_adapter *adapter)
{ {
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
return i2c_detect(adapter, &addr_data, lm85_detect); return i2c_detect(adapter, &addr_data, lm85_detect);
} }
......
...@@ -187,7 +187,7 @@ struct lm90_data { ...@@ -187,7 +187,7 @@ struct lm90_data {
* Internal variables * Internal variables
*/ */
static int lm90_id = 0; static int lm90_id;
/* /*
* Sysfs stuff * Sysfs stuff
...@@ -214,7 +214,8 @@ static ssize_t set_##value(struct device *dev, const char *buf, \ ...@@ -214,7 +214,8 @@ static ssize_t set_##value(struct device *dev, const char *buf, \
{ \ { \
struct i2c_client *client = to_i2c_client(dev); \ struct i2c_client *client = to_i2c_client(dev); \
struct lm90_data *data = i2c_get_clientdata(client); \ struct lm90_data *data = i2c_get_clientdata(client); \
data->value = TEMP1_TO_REG(simple_strtol(buf, NULL, 10)); \ long val = simple_strtol(buf, NULL, 10); \
data->value = TEMP1_TO_REG(val); \
i2c_smbus_write_byte_data(client, reg, data->value); \ i2c_smbus_write_byte_data(client, reg, data->value); \
return count; \ return count; \
} }
...@@ -224,7 +225,8 @@ static ssize_t set_##value(struct device *dev, const char *buf, \ ...@@ -224,7 +225,8 @@ static ssize_t set_##value(struct device *dev, const char *buf, \
{ \ { \
struct i2c_client *client = to_i2c_client(dev); \ struct i2c_client *client = to_i2c_client(dev); \
struct lm90_data *data = i2c_get_clientdata(client); \ struct lm90_data *data = i2c_get_clientdata(client); \
data->value = TEMP2_TO_REG(simple_strtol(buf, NULL, 10)); \ long val = simple_strtol(buf, NULL, 10); \
data->value = TEMP2_TO_REG(val); \
i2c_smbus_write_byte_data(client, regh, data->value >> 8); \ i2c_smbus_write_byte_data(client, regh, data->value >> 8); \
i2c_smbus_write_byte_data(client, regl, data->value & 0xff); \ i2c_smbus_write_byte_data(client, regl, data->value & 0xff); \
return count; \ return count; \
......
...@@ -120,7 +120,7 @@ struct max1619_data { ...@@ -120,7 +120,7 @@ struct max1619_data {
* Internal variables * Internal variables
*/ */
static int max1619_id = 0; static int max1619_id;
/* /*
* Sysfs stuff * Sysfs stuff
...@@ -145,7 +145,8 @@ static ssize_t set_##value(struct device *dev, const char *buf, \ ...@@ -145,7 +145,8 @@ static ssize_t set_##value(struct device *dev, const char *buf, \
{ \ { \
struct i2c_client *client = to_i2c_client(dev); \ struct i2c_client *client = to_i2c_client(dev); \
struct max1619_data *data = i2c_get_clientdata(client); \ struct max1619_data *data = i2c_get_clientdata(client); \
data->value = TEMP_TO_REG(simple_strtol(buf, NULL, 10)); \ long val = simple_strtol(buf, NULL, 10); \
data->value = TEMP_TO_REG(val); \
i2c_smbus_write_byte_data(client, reg, data->value); \ i2c_smbus_write_byte_data(client, reg, data->value); \
return count; \ return count; \
} }
......
...@@ -77,7 +77,7 @@ static struct i2c_driver pcf8574_driver = { ...@@ -77,7 +77,7 @@ static struct i2c_driver pcf8574_driver = {
.detach_client = pcf8574_detach_client, .detach_client = pcf8574_detach_client,
}; };
static int pcf8574_id = 0; static int pcf8574_id;
/* following are the sysfs callback functions */ /* following are the sysfs callback functions */
static ssize_t show_read(struct device *dev, char *buf) static ssize_t show_read(struct device *dev, char *buf)
......
...@@ -99,7 +99,7 @@ static struct i2c_driver pcf8591_driver = { ...@@ -99,7 +99,7 @@ static struct i2c_driver pcf8591_driver = {
.detach_client = pcf8591_detach_client, .detach_client = pcf8591_detach_client,
}; };
static int pcf8591_id = 0; static int pcf8591_id;
/* following are the sysfs callback functions */ /* following are the sysfs callback functions */
#define show_in_channel(channel) \ #define show_in_channel(channel) \
......
...@@ -1062,6 +1062,9 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -1062,6 +1062,9 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
if (is_isa) if (is_isa)
if (!request_region(address, W83781D_EXTENT, "w83781d")) { if (!request_region(address, W83781D_EXTENT, "w83781d")) {
dev_dbg(&adapter->dev, "Request of region "
"0x%x-0x%x for w83781d failed\n", address,
address + W83781D_EXTENT - 1);
err = -EBUSY; err = -EBUSY;
goto ERROR0; goto ERROR0;
} }
...@@ -1075,15 +1078,11 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -1075,15 +1078,11 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
/* We need the timeouts for at least some LM78-like /* We need the timeouts for at least some LM78-like
chips. But only if we read 'undefined' registers. */ chips. But only if we read 'undefined' registers. */
i = inb_p(address + 1); i = inb_p(address + 1);
if (inb_p(address + 2) != i) { if (inb_p(address + 2) != i
err = -ENODEV; || inb_p(address + 3) != i
goto ERROR1; || inb_p(address + 7) != i) {
} dev_dbg(&adapter->dev, "Detection of w83781d "
if (inb_p(address + 3) != i) { "chip failed at step 1\n");
err = -ENODEV;
goto ERROR1;
}
if (inb_p(address + 7) != i) {
err = -ENODEV; err = -ENODEV;
goto ERROR1; goto ERROR1;
} }
...@@ -1092,8 +1091,13 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -1092,8 +1091,13 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
/* Let's just hope nothing breaks here */ /* Let's just hope nothing breaks here */
i = inb_p(address + 5) & 0x7f; i = inb_p(address + 5) & 0x7f;
outb_p(~i & 0x7f, address + 5); outb_p(~i & 0x7f, address + 5);
if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) { val2 = inb_p(address + 5) & 0x7f;
if (val2 != (~i & 0x7f)) {
outb_p(i, address + 5); outb_p(i, address + 5);
dev_dbg(&adapter->dev, "Detection of w83781d "
"chip failed at step 2 (0x%x != "
"0x%x at 0x%x)\n", val2, ~i & 0x7f,
address + 5);
err = -ENODEV; err = -ENODEV;
goto ERROR1; goto ERROR1;
} }
...@@ -1125,7 +1129,9 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -1125,7 +1129,9 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
force_*=... parameter, and the Winbond will be reset to the right force_*=... parameter, and the Winbond will be reset to the right
bank. */ bank. */
if (kind < 0) { if (kind < 0) {
if (w83781d_read_value(new_client, W83781D_REG_CONFIG) & 0x80){ if (w83781d_read_value(new_client, W83781D_REG_CONFIG) & 0x80) {
dev_dbg(&new_client->dev, "Detection failed at step "
"3\n");
err = -ENODEV; err = -ENODEV;
goto ERROR2; goto ERROR2;
} }
...@@ -1135,6 +1141,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -1135,6 +1141,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
if ((!(val1 & 0x07)) && if ((!(val1 & 0x07)) &&
(((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3)) (((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3))
|| ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12)))) { || ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12)))) {
dev_dbg(&new_client->dev, "Detection failed at step "
"4\n");
err = -ENODEV; err = -ENODEV;
goto ERROR2; goto ERROR2;
} }
...@@ -1144,6 +1152,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -1144,6 +1152,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
((val1 & 0x80) && (val2 == 0x5c)))) { ((val1 & 0x80) && (val2 == 0x5c)))) {
if (w83781d_read_value if (w83781d_read_value
(new_client, W83781D_REG_I2C_ADDR) != address) { (new_client, W83781D_REG_I2C_ADDR) != address) {
dev_dbg(&new_client->dev, "Detection failed "
"at step 5\n");
err = -ENODEV; err = -ENODEV;
goto ERROR2; goto ERROR2;
} }
...@@ -1166,6 +1176,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -1166,6 +1176,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
else if (val2 == 0x12) else if (val2 == 0x12)
vendid = asus; vendid = asus;
else { else {
dev_dbg(&new_client->dev, "Chip was made by neither "
"Winbond nor Asus?\n");
err = -ENODEV; err = -ENODEV;
goto ERROR2; goto ERROR2;
} }
...@@ -1186,10 +1198,10 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -1186,10 +1198,10 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
kind = w83697hf; kind = w83697hf;
else { else {
if (kind == 0) if (kind == 0)
dev_warn(&new_client->dev, dev_warn(&new_client->dev, "Ignoring 'force' "
"Ignoring 'force' parameter for unknown chip at" "parameter for unknown chip at "
"adapter %d, address 0x%02x\n", "adapter %d, address 0x%02x\n",
i2c_adapter_id(adapter), address); i2c_adapter_id(adapter), address);
err = -EINVAL; err = -EINVAL;
goto ERROR2; goto ERROR2;
} }
......
...@@ -2,6 +2,10 @@ ...@@ -2,6 +2,10 @@
# Makefile for the Dallas's 1-wire bus. # Makefile for the Dallas's 1-wire bus.
# #
ifneq ($(CONFIG_NET), y)
EXTRA_CFLAGS += -DNETLINK_DISABLED
endif
obj-$(CONFIG_W1) += wire.o obj-$(CONFIG_W1) += wire.o
wire-objs := w1.o w1_int.o w1_family.o w1_netlink.o w1_io.o wire-objs := w1.o w1_int.o w1_family.o w1_netlink.o w1_io.o
......
...@@ -47,9 +47,11 @@ MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol."); ...@@ -47,9 +47,11 @@ MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol.");
static int w1_timeout = 10; static int w1_timeout = 10;
int w1_max_slave_count = 10; int w1_max_slave_count = 10;
int w1_max_slave_ttl = 10;
module_param_named(timeout, w1_timeout, int, 0); module_param_named(timeout, w1_timeout, int, 0);
module_param_named(max_slave_count, w1_max_slave_count, int, 0); module_param_named(max_slave_count, w1_max_slave_count, int, 0);
module_param_named(slave_ttl, w1_max_slave_ttl, int, 0);
spinlock_t w1_mlock = SPIN_LOCK_UNLOCKED; spinlock_t w1_mlock = SPIN_LOCK_UNLOCKED;
LIST_HEAD(w1_masters); LIST_HEAD(w1_masters);
...@@ -431,6 +433,7 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn) ...@@ -431,6 +433,7 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
return err; return err;
} }
sl->ttl = dev->slave_ttl;
dev->slave_count++; dev->slave_count++;
memcpy(&msg.id.id, rn, sizeof(msg.id.id)); memcpy(&msg.id.id, rn, sizeof(msg.id.id));
...@@ -569,7 +572,7 @@ static void w1_search(struct w1_master *dev) ...@@ -569,7 +572,7 @@ static void w1_search(struct w1_master *dev)
} }
if (slave_count == dev->slave_count && if (slave_count == dev->slave_count &&
((rn >> 56) & 0xff) == w1_calc_crc8((u8 *)&rn, 7)) { rn && ((rn >> 56) & 0xff) == w1_calc_crc8((u8 *)&rn, 7)) {
w1_attach_slave_device(dev, (struct w1_reg_num *) &rn); w1_attach_slave_device(dev, (struct w1_reg_num *) &rn);
} }
} }
...@@ -718,7 +721,7 @@ int w1_process(void *data) ...@@ -718,7 +721,7 @@ int w1_process(void *data)
list_for_each_safe(ent, n, &dev->slist) { list_for_each_safe(ent, n, &dev->slist) {
sl = list_entry(ent, struct w1_slave, w1_slave_entry); sl = list_entry(ent, struct w1_slave, w1_slave_entry);
if (sl && !test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags)) { if (sl && !test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) {
list_del (&sl->w1_slave_entry); list_del (&sl->w1_slave_entry);
w1_slave_detach (sl); w1_slave_detach (sl);
...@@ -726,6 +729,8 @@ int w1_process(void *data) ...@@ -726,6 +729,8 @@ int w1_process(void *data)
dev->slave_count--; dev->slave_count--;
} }
else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags))
sl->ttl = dev->slave_ttl;
} }
up(&dev->mutex); up(&dev->mutex);
} }
......
...@@ -63,6 +63,7 @@ struct w1_slave ...@@ -63,6 +63,7 @@ struct w1_slave
atomic_t refcnt; atomic_t refcnt;
u8 rom[9]; u8 rom[9];
u32 flags; u32 flags;
int ttl;
struct w1_master *master; struct w1_master *master;
struct w1_family *family; struct w1_family *family;
...@@ -99,6 +100,7 @@ struct w1_master ...@@ -99,6 +100,7 @@ struct w1_master
struct list_head slist; struct list_head slist;
int max_slave_count, slave_count; int max_slave_count, slave_count;
unsigned long attempts; unsigned long attempts;
int slave_ttl;
int initialized; int initialized;
u32 id; u32 id;
......
...@@ -32,12 +32,13 @@ extern struct device_driver w1_driver; ...@@ -32,12 +32,13 @@ extern struct device_driver w1_driver;
extern struct bus_type w1_bus_type; extern struct bus_type w1_bus_type;
extern struct device w1_device; extern struct device w1_device;
extern int w1_max_slave_count; extern int w1_max_slave_count;
extern int w1_max_slave_ttl;
extern struct list_head w1_masters; extern struct list_head w1_masters;
extern spinlock_t w1_mlock; extern spinlock_t w1_mlock;
extern int w1_process(void *); extern int w1_process(void *);
struct w1_master * w1_alloc_dev(u32 id, int slave_count, struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
struct device_driver *driver, struct device *device) struct device_driver *driver, struct device *device)
{ {
struct w1_master *dev; struct w1_master *dev;
...@@ -65,6 +66,7 @@ struct w1_master * w1_alloc_dev(u32 id, int slave_count, ...@@ -65,6 +66,7 @@ struct w1_master * w1_alloc_dev(u32 id, int slave_count,
dev->kpid = -1; dev->kpid = -1;
dev->initialized = 0; dev->initialized = 0;
dev->id = id; dev->id = id;
dev->slave_ttl = slave_ttl;
atomic_set(&dev->refcnt, 2); atomic_set(&dev->refcnt, 2);
...@@ -121,7 +123,7 @@ int w1_add_master_device(struct w1_bus_master *master) ...@@ -121,7 +123,7 @@ int w1_add_master_device(struct w1_bus_master *master)
int retval = 0; int retval = 0;
struct w1_netlink_msg msg; struct w1_netlink_msg msg;
dev = w1_alloc_dev(w1_ids++, w1_max_slave_count, &w1_driver, &w1_device); dev = w1_alloc_dev(w1_ids++, w1_max_slave_count, w1_max_slave_ttl, &w1_driver, &w1_device);
if (!dev) if (!dev)
return -ENOMEM; return -ENOMEM;
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#include "w1.h" #include "w1.h"
struct w1_master * w1_alloc_dev(int, struct device_driver *, struct device *); struct w1_master * w1_alloc_dev(u32, int, int, struct device_driver *, struct device *);
void w1_free_dev(struct w1_master *dev); void w1_free_dev(struct w1_master *dev);
int w1_add_master_device(struct w1_bus_master *); int w1_add_master_device(struct w1_bus_master *);
void w1_remove_master_device(struct w1_bus_master *); void w1_remove_master_device(struct w1_bus_master *);
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "w1_log.h" #include "w1_log.h"
#include "w1_netlink.h" #include "w1_netlink.h"
#ifndef NETLINK_DISABLED
void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg) void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg)
{ {
unsigned int size; unsigned int size;
...@@ -53,3 +54,10 @@ void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg) ...@@ -53,3 +54,10 @@ void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg)
nlmsg_failure: nlmsg_failure:
return; return;
} }
#else
#warning Netlink support is disabled. Please compile with NET support enabled.
void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg)
{
}
#endif
...@@ -59,19 +59,28 @@ static ssize_t w1_therm_read_name(struct device *dev, char *buf) ...@@ -59,19 +59,28 @@ static ssize_t w1_therm_read_name(struct device *dev, char *buf)
return sprintf(buf, "%s\n", sl->name); return sprintf(buf, "%s\n", sl->name);
} }
static inline int w1_convert_temp(u8 rom[9])
{
int t, h;
if (rom[1] == 0)
t = ((s32)rom[0] >> 1)*1000;
else
t = 1000*(-1*(s32)(0x100-rom[0]) >> 1);
t -= 250;
h = 1000*((s32)rom[7] - (s32)rom[6]);
h /= (s32)rom[7];
t += h;
return t;
}
static ssize_t w1_therm_read_temp(struct device *dev, char *buf) static ssize_t w1_therm_read_temp(struct device *dev, char *buf)
{ {
struct w1_slave *sl = container_of(dev, struct w1_slave, dev); struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
s16 temp;
/* return sprintf(buf, "%d\n", w1_convert_temp(sl->rom));
* Must be more precise.
*/
temp = 0;
temp <<= sl->rom[1] / 2;
temp |= sl->rom[0] / 2;
return sprintf(buf, "%d\n", temp * 1000);
} }
static int w1_therm_check_rom(u8 rom[9]) static int w1_therm_check_rom(u8 rom[9])
...@@ -92,7 +101,6 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si ...@@ -92,7 +101,6 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
struct w1_master *dev = sl->master; struct w1_master *dev = sl->master;
u8 rom[9], crc, verdict; u8 rom[9], crc, verdict;
int i, max_trying = 10; int i, max_trying = 10;
u16 temp;
atomic_inc(&sl->refcnt); atomic_inc(&sl->refcnt);
if (down_interruptible(&sl->master->mutex)) { if (down_interruptible(&sl->master->mutex)) {
...@@ -120,6 +128,7 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si ...@@ -120,6 +128,7 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
if (!w1_reset_bus (dev)) { if (!w1_reset_bus (dev)) {
int count = 0; int count = 0;
u8 match[9] = {W1_MATCH_ROM, }; u8 match[9] = {W1_MATCH_ROM, };
unsigned long tm;
memcpy(&match[1], (u64 *) & sl->reg_num, 8); memcpy(&match[1], (u64 *) & sl->reg_num, 8);
...@@ -127,24 +136,29 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si ...@@ -127,24 +136,29 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
w1_write_8(dev, W1_CONVERT_TEMP); w1_write_8(dev, W1_CONVERT_TEMP);
if (count < 10) { tm = jiffies + msecs_to_jiffies(750);
if (!w1_reset_bus(dev)) { while(time_before(jiffies, tm)) {
w1_write_block(dev, match, 9); set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(tm-jiffies);
w1_write_8(dev, W1_READ_SCRATCHPAD);
if ((count = w1_read_block(dev, rom, 9)) != 9) {
dev_warn(&dev->dev, "w1_read_block() returned %d instead of 9.\n", count);
}
crc = w1_calc_crc8(rom, 8); if (signal_pending(current))
flush_signals(current);
}
if (rom[8] == crc && rom[0]) if (!w1_reset_bus (dev)) {
verdict = 1; w1_write_block(dev, match, 9);
w1_write_8(dev, W1_READ_SCRATCHPAD);
if ((count = w1_read_block(dev, rom, 9)) != 9) {
dev_warn(&dev->dev, "w1_read_block() returned %d instead of 9.\n", count);
} }
crc = w1_calc_crc8(rom, 8);
if (rom[8] == crc && rom[0])
verdict = 1;
} }
else
dev_warn(&dev->dev,
"18S20 doesn't respond to CONVERT_TEMP.\n");
} }
if (!w1_therm_check_rom(rom)) if (!w1_therm_check_rom(rom))
...@@ -157,12 +171,13 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si ...@@ -157,12 +171,13 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
crc, (verdict) ? "YES" : "NO"); crc, (verdict) ? "YES" : "NO");
if (verdict) if (verdict)
memcpy(sl->rom, rom, sizeof(sl->rom)); memcpy(sl->rom, rom, sizeof(sl->rom));
else
dev_warn(&dev->dev, "18S20 doesn't respond to CONVERT_TEMP.\n");
for (i = 0; i < 9; ++i) for (i = 0; i < 9; ++i)
count += sprintf(buf + count, "%02x ", sl->rom[i]); count += sprintf(buf + count, "%02x ", sl->rom[i]);
temp = 0;
temp <<= sl->rom[1] / 2; count += sprintf(buf + count, "t=%d\n", w1_convert_temp(rom));
temp |= sl->rom[0] / 2;
count += sprintf(buf + count, "t=%u\n", temp);
out: out:
up(&dev->mutex); up(&dev->mutex);
out_dec: out_dec:
......
...@@ -29,7 +29,22 @@ ...@@ -29,7 +29,22 @@
*/ */
/* /*
Legal val values 00 - 1F. AMD Opteron processors don't follow the Intel VRM spec.
I'm going to "make up" 2.4 as the VRM spec for the Opterons.
No good reason just a mnemonic for the 24x Opteron processor
series
Opteron VID encoding is:
00000 = 1.550 V
00001 = 1.525 V
. . . .
11110 = 0.800 V
11111 = 0.000 V (off)
*/
/*
Legal val values 0x00 - 0x1f; except for VRD 10.0, 0x00 - 0x3f.
vrm is the Intel VRM document version. vrm is the Intel VRM document version.
Note: vrm version is scaled by 10 and the return value is scaled by 1000 Note: vrm version is scaled by 10 and the return value is scaled by 1000
to avoid floating point in the kernel. to avoid floating point in the kernel.
...@@ -41,9 +56,28 @@ int i2c_which_vrm(void); ...@@ -41,9 +56,28 @@ int i2c_which_vrm(void);
static inline int vid_from_reg(int val, int vrm) static inline int vid_from_reg(int val, int vrm)
{ {
int vid;
switch(vrm) { switch(vrm) {
case 0: case 0:
return 0; return 0;
case 100: /* VRD 10.0 */
if((val & 0x1f) == 0x1f)
return 0;
if((val & 0x1f) <= 0x09 || val == 0x0a)
vid = 10875 - (val & 0x1f) * 250;
else
vid = 18625 - (val & 0x1f) * 250;
if(val & 0x20)
vid -= 125;
vid /= 10; /* only return 3 dec. places for now */
return vid;
case 24: /* Opteron processor */
return(val == 0x1f ? 0 : 1550 - val * 25);
case 91: /* VRM 9.1 */ case 91: /* VRM 9.1 */
case 90: /* VRM 9.0 */ case 90: /* VRM 9.0 */
return(val == 0x1f ? 0 : return(val == 0x1f ? 0 :
......
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