summaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/Kconfig5
-rw-r--r--drivers/i2c/busses/i2c-i801.c5
-rw-r--r--drivers/i2c/busses/i2c-parport-light.c9
-rw-r--r--drivers/i2c/busses/i2c-parport.c9
-rw-r--r--drivers/i2c/busses/i2c-parport.h2
-rw-r--r--drivers/i2c/busses/i2c-sis96x.c8
-rw-r--r--drivers/i2c/busses/scx200_acb.c18
-rw-r--r--drivers/i2c/chips/ds1374.c16
-rw-r--r--drivers/i2c/chips/m41t00.c24
9 files changed, 59 insertions, 37 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 089c6f5b24de..d6d44946a283 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -286,7 +286,10 @@ config I2C_PARPORT
This driver is a replacement for (and was inspired by) an older
driver named i2c-philips-par. The new driver supports more devices,
and makes it easier to add support for new devices.
-
+
+ An adapter type parameter is now mandatory. Please read the file
+ Documentation/i2c/busses/i2c-parport for details.
+
Another driver exists, named i2c-parport-light, which doesn't depend
on the parport driver. This is meant for embedded systems. Don't say
Y here if you intend to say Y or M there.
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 8e0f3158215f..dfca74933625 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -478,6 +478,11 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
ret = i801_transaction();
}
+ /* Some BIOSes don't like it when PEC is enabled at reboot or resume
+ time, so we forcibly disable it after every transaction. */
+ if (hwpec)
+ outb_p(0, SMBAUXCTL);
+
if(block)
return ret;
if(ret)
diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c
index c63025a4c861..e09ebbb2f9f0 100644
--- a/drivers/i2c/busses/i2c-parport-light.c
+++ b/drivers/i2c/busses/i2c-parport-light.c
@@ -121,9 +121,14 @@ static struct i2c_adapter parport_adapter = {
static int __init i2c_parport_init(void)
{
- if (type < 0 || type >= ARRAY_SIZE(adapter_parm)) {
+ if (type < 0) {
+ printk(KERN_WARNING "i2c-parport: adapter type unspecified\n");
+ return -ENODEV;
+ }
+
+ if (type >= ARRAY_SIZE(adapter_parm)) {
printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type);
- type = 0;
+ return -ENODEV;
}
if (base == 0) {
diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c
index 7e2e8cd1c14a..934bd55bae15 100644
--- a/drivers/i2c/busses/i2c-parport.c
+++ b/drivers/i2c/busses/i2c-parport.c
@@ -241,9 +241,14 @@ static struct parport_driver i2c_parport_driver = {
static int __init i2c_parport_init(void)
{
- if (type < 0 || type >= ARRAY_SIZE(adapter_parm)) {
+ if (type < 0) {
+ printk(KERN_WARNING "i2c-parport: adapter type unspecified\n");
+ return -ENODEV;
+ }
+
+ if (type >= ARRAY_SIZE(adapter_parm)) {
printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type);
- type = 0;
+ return -ENODEV;
}
return parport_register_driver(&i2c_parport_driver);
diff --git a/drivers/i2c/busses/i2c-parport.h b/drivers/i2c/busses/i2c-parport.h
index d702e5e0388d..9ddd816d5d0f 100644
--- a/drivers/i2c/busses/i2c-parport.h
+++ b/drivers/i2c/busses/i2c-parport.h
@@ -90,7 +90,7 @@ static struct adapter_parm adapter_parm[] = {
},
};
-static int type;
+static int type = -1;
module_param(type, int, 0);
MODULE_PARM_DESC(type,
"Type of adapter:\n"
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
index 3024907cdafe..1a73c0532fc7 100644
--- a/drivers/i2c/busses/i2c-sis96x.c
+++ b/drivers/i2c/busses/i2c-sis96x.c
@@ -43,13 +43,6 @@
#include <linux/init.h>
#include <asm/io.h>
-/*
- HISTORY:
- 2003-05-11 1.0.0 Updated from lm_sensors project for kernel 2.5
- (was i2c-sis645.c from lm_sensors 2.7.0)
-*/
-#define SIS96x_VERSION "1.0.0"
-
/* base address register in PCI config space */
#define SIS96x_BAR 0x04
@@ -337,7 +330,6 @@ static struct pci_driver sis96x_driver = {
static int __init i2c_sis96x_init(void)
{
- printk(KERN_INFO "i2c-sis96x version %s\n", SIS96x_VERSION);
return pci_register_driver(&sis96x_driver);
}
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index 8bd305e47f0d..766cc969c4d0 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -133,6 +133,9 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status)
outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1);
outb(ACBST_STASTR | ACBST_NEGACK, ACBST);
+
+ /* Reset the status register */
+ outb(0, ACBST);
return;
}
@@ -228,6 +231,10 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface)
timeout = jiffies + POLL_TIMEOUT;
while (time_before(jiffies, timeout)) {
status = inb(ACBST);
+
+ /* Reset the status register to avoid the hang */
+ outb(0, ACBST);
+
if ((status & (ACBST_SDAST|ACBST_BER|ACBST_NEGACK)) != 0) {
scx200_acb_machine(iface, status);
return;
@@ -415,7 +422,6 @@ static int __init scx200_acb_create(const char *text, int base, int index)
struct scx200_acb_iface *iface;
struct i2c_adapter *adapter;
int rc;
- char description[64];
iface = kzalloc(sizeof(*iface), GFP_KERNEL);
if (!iface) {
@@ -434,10 +440,7 @@ static int __init scx200_acb_create(const char *text, int base, int index)
mutex_init(&iface->mutex);
- snprintf(description, sizeof(description), "%s ACCESS.bus [%s]",
- text, adapter->name);
-
- if (request_region(base, 8, description) == 0) {
+ if (!request_region(base, 8, adapter->name)) {
printk(KERN_ERR NAME ": can't allocate io 0x%x-0x%x\n",
base, base + 8-1);
rc = -EBUSY;
@@ -488,7 +491,7 @@ static struct pci_device_id divil_pci[] = {
#define MSR_LBAR_SMB 0x5140000B
-static int scx200_add_cs553x(void)
+static __init int scx200_add_cs553x(void)
{
u32 low, hi;
u32 smb_base;
@@ -524,6 +527,9 @@ static int __init scx200_acb_init(void)
} else if (pci_dev_present(divil_pci))
rc = scx200_add_cs553x();
+ /* If at least one bus was created, init must succeed */
+ if (scx200_acb_list)
+ return 0;
return rc;
}
diff --git a/drivers/i2c/chips/ds1374.c b/drivers/i2c/chips/ds1374.c
index 03d09ed5ec2c..4630f1969a09 100644
--- a/drivers/i2c/chips/ds1374.c
+++ b/drivers/i2c/chips/ds1374.c
@@ -27,6 +27,7 @@
#include <linux/rtc.h>
#include <linux/bcd.h>
#include <linux/mutex.h>
+#include <linux/workqueue.h>
#define DS1374_REG_TOD0 0x00
#define DS1374_REG_TOD1 0x01
@@ -139,7 +140,7 @@ ulong ds1374_get_rtc_time(void)
return t1;
}
-static void ds1374_set_tlet(ulong arg)
+static void ds1374_set_work(void *arg)
{
ulong t1, t2;
int limit = 10; /* arbitrary retry limit */
@@ -168,17 +169,18 @@ static void ds1374_set_tlet(ulong arg)
static ulong new_time;
-static DECLARE_TASKLET_DISABLED(ds1374_tasklet, ds1374_set_tlet,
- (ulong) & new_time);
+static struct workqueue_struct *ds1374_workqueue;
+
+static DECLARE_WORK(ds1374_work, ds1374_set_work, &new_time);
int ds1374_set_rtc_time(ulong nowtime)
{
new_time = nowtime;
if (in_interrupt())
- tasklet_schedule(&ds1374_tasklet);
+ queue_work(ds1374_workqueue, &ds1374_work);
else
- ds1374_set_tlet((ulong) & new_time);
+ ds1374_set_work(&new_time);
return 0;
}
@@ -204,6 +206,8 @@ static int ds1374_probe(struct i2c_adapter *adap, int addr, int kind)
client->adapter = adap;
client->driver = &ds1374_driver;
+ ds1374_workqueue = create_singlethread_workqueue("ds1374");
+
if ((rc = i2c_attach_client(client)) != 0) {
kfree(client);
return rc;
@@ -227,7 +231,7 @@ static int ds1374_detach(struct i2c_client *client)
if ((rc = i2c_detach_client(client)) == 0) {
kfree(i2c_get_clientdata(client));
- tasklet_kill(&ds1374_tasklet);
+ destroy_workqueue(ds1374_workqueue);
}
return rc;
}
diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c
index b5aabe7cf792..99ab4ec34390 100644
--- a/drivers/i2c/chips/m41t00.c
+++ b/drivers/i2c/chips/m41t00.c
@@ -25,6 +25,7 @@
#include <linux/rtc.h>
#include <linux/bcd.h>
#include <linux/mutex.h>
+#include <linux/workqueue.h>
#include <asm/time.h>
#include <asm/rtc.h>
@@ -111,7 +112,7 @@ m41t00_get_rtc_time(void)
}
static void
-m41t00_set_tlet(ulong arg)
+m41t00_set(void *arg)
{
struct rtc_time tm;
ulong nowtime = *(ulong *)arg;
@@ -130,13 +131,13 @@ m41t00_set_tlet(ulong arg)
if ((i2c_smbus_write_byte_data(save_client, 0, tm.tm_sec & 0x7f) < 0)
|| (i2c_smbus_write_byte_data(save_client, 1, tm.tm_min & 0x7f)
< 0)
- || (i2c_smbus_write_byte_data(save_client, 2, tm.tm_hour & 0x7f)
+ || (i2c_smbus_write_byte_data(save_client, 2, tm.tm_hour & 0x3f)
< 0)
- || (i2c_smbus_write_byte_data(save_client, 4, tm.tm_mday & 0x7f)
+ || (i2c_smbus_write_byte_data(save_client, 4, tm.tm_mday & 0x3f)
< 0)
- || (i2c_smbus_write_byte_data(save_client, 5, tm.tm_mon & 0x7f)
+ || (i2c_smbus_write_byte_data(save_client, 5, tm.tm_mon & 0x1f)
< 0)
- || (i2c_smbus_write_byte_data(save_client, 6, tm.tm_year & 0x7f)
+ || (i2c_smbus_write_byte_data(save_client, 6, tm.tm_year & 0xff)
< 0))
dev_warn(&save_client->dev,"m41t00: can't write to rtc chip\n");
@@ -145,9 +146,9 @@ m41t00_set_tlet(ulong arg)
return;
}
-static ulong new_time;
-
-DECLARE_TASKLET_DISABLED(m41t00_tasklet, m41t00_set_tlet, (ulong)&new_time);
+static ulong new_time;
+static struct workqueue_struct *m41t00_wq;
+static DECLARE_WORK(m41t00_work, m41t00_set, &new_time);
int
m41t00_set_rtc_time(ulong nowtime)
@@ -155,9 +156,9 @@ m41t00_set_rtc_time(ulong nowtime)
new_time = nowtime;
if (in_interrupt())
- tasklet_schedule(&m41t00_tasklet);
+ queue_work(m41t00_wq, &m41t00_work);
else
- m41t00_set_tlet((ulong)&new_time);
+ m41t00_set(&new_time);
return 0;
}
@@ -189,6 +190,7 @@ m41t00_probe(struct i2c_adapter *adap, int addr, int kind)
return rc;
}
+ m41t00_wq = create_singlethread_workqueue("m41t00");
save_client = client;
return 0;
}
@@ -206,7 +208,7 @@ m41t00_detach(struct i2c_client *client)
if ((rc = i2c_detach_client(client)) == 0) {
kfree(client);
- tasklet_kill(&m41t00_tasklet);
+ destroy_workqueue(m41t00_wq);
}
return rc;
}
OpenPOWER on IntegriCloud