summaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/Kconfig11
-rw-r--r--drivers/i2c/busses/i2c-ali1535.c4
-rw-r--r--drivers/i2c/busses/i2c-amd756-s4882.c13
-rw-r--r--drivers/i2c/busses/i2c-frodo.c85
-rw-r--r--drivers/i2c/busses/i2c-iop3xx.c9
-rw-r--r--drivers/i2c/busses/i2c-isa.c2
-rw-r--r--drivers/i2c/busses/i2c-ite.c4
-rw-r--r--drivers/i2c/busses/i2c-ixp4xx.c1
-rw-r--r--drivers/i2c/busses/i2c-mpc.c5
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c4
-rw-r--r--drivers/i2c/busses/i2c-piix4.c4
-rw-r--r--drivers/i2c/busses/i2c-pxa.c2
-rw-r--r--drivers/i2c/busses/scx200_acb.c283
-rw-r--r--drivers/i2c/chips/Kconfig18
-rw-r--r--drivers/i2c/chips/Makefile2
-rw-r--r--drivers/i2c/chips/ds1374.c11
-rw-r--r--drivers/i2c/chips/eeprom.c9
-rw-r--r--drivers/i2c/chips/isp1301_omap.c2
-rw-r--r--drivers/i2c/chips/m41t00.c11
-rw-r--r--drivers/i2c/chips/max6875.c10
-rw-r--r--drivers/i2c/chips/pcf8591.c13
-rw-r--r--drivers/i2c/chips/rtc8564.c385
-rw-r--r--drivers/i2c/chips/rtc8564.h78
-rw-r--r--drivers/i2c/chips/tps65010.c45
-rw-r--r--drivers/i2c/chips/x1205.c698
-rw-r--r--drivers/i2c/i2c-core.c81
26 files changed, 266 insertions, 1524 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index ff92735c7c85..089c6f5b24de 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -168,12 +168,14 @@ config I2C_PIIX4
help
If you say yes to this option, support will be included for the Intel
PIIX4 family of mainboard I2C interfaces. Specifically, the following
- versions of the chipset are supported:
+ versions of the chipset are supported (note that Serverworks is part
+ of Broadcom):
Intel PIIX4
Intel 440MX
Serverworks OSB4
Serverworks CSB5
Serverworks CSB6
+ Serverworks HT-1000
SMSC Victory66
This driver can also be built as a module. If so, the module
@@ -389,10 +391,11 @@ config SCx200_I2C_SDA
also be specified with a module parameter.
config SCx200_ACB
- tristate "NatSemi SCx200 ACCESS.bus"
- depends on I2C && PCI
+ tristate "Geode ACCESS.bus support"
+ depends on X86_32 && I2C && PCI
help
- Enable the use of the ACCESS.bus controllers of a SCx200 processor.
+ Enable the use of the ACCESS.bus controllers on the Geode SCx200 and
+ SC1100 processors and the CS5535 and CS5536 Geode companion devices.
If you don't know what to do here, say N.
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c
index 3eb47890db40..d3ef46aeeb3c 100644
--- a/drivers/i2c/busses/i2c-ali1535.c
+++ b/drivers/i2c/busses/i2c-ali1535.c
@@ -63,7 +63,6 @@
#include <linux/i2c.h>
#include <linux/init.h>
#include <asm/io.h>
-#include <asm/semaphore.h>
/* ALI1535 SMBus address offsets */
@@ -136,7 +135,6 @@
static struct pci_driver ali1535_driver;
static unsigned short ali1535_smba;
-static DECLARE_MUTEX(i2c_ali1535_sem);
/* Detect whether a ALI1535 can be found, and initialize it, where necessary.
Note the differences between kernels with the old PCI BIOS interface and
@@ -345,7 +343,6 @@ static s32 ali1535_access(struct i2c_adapter *adap, u16 addr,
int timeout;
s32 result = 0;
- down(&i2c_ali1535_sem);
/* make sure SMBus is idle */
temp = inb_p(SMBHSTSTS);
for (timeout = 0;
@@ -460,7 +457,6 @@ static s32 ali1535_access(struct i2c_adapter *adap, u16 addr,
break;
}
EXIT:
- up(&i2c_ali1535_sem);
return result;
}
diff --git a/drivers/i2c/busses/i2c-amd756-s4882.c b/drivers/i2c/busses/i2c-amd756-s4882.c
index 56c7d987590f..08e915730caf 100644
--- a/drivers/i2c/busses/i2c-amd756-s4882.c
+++ b/drivers/i2c/busses/i2c-amd756-s4882.c
@@ -38,6 +38,7 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/i2c.h>
+#include <linux/mutex.h>
extern struct i2c_adapter amd756_smbus;
@@ -45,7 +46,7 @@ static struct i2c_adapter *s4882_adapter;
static struct i2c_algorithm *s4882_algo;
/* Wrapper access functions for multiplexed SMBus */
-static struct semaphore amd756_lock;
+static DEFINE_MUTEX(amd756_lock);
static s32 amd756_access_virt0(struct i2c_adapter * adap, u16 addr,
unsigned short flags, char read_write,
@@ -59,12 +60,12 @@ static s32 amd756_access_virt0(struct i2c_adapter * adap, u16 addr,
|| addr == 0x18)
return -1;
- down(&amd756_lock);
+ mutex_lock(&amd756_lock);
error = amd756_smbus.algo->smbus_xfer(adap, addr, flags, read_write,
command, size, data);
- up(&amd756_lock);
+ mutex_unlock(&amd756_lock);
return error;
}
@@ -87,7 +88,7 @@ static inline s32 amd756_access_channel(struct i2c_adapter * adap, u16 addr,
if (addr != 0x4c && (addr & 0xfc) != 0x50 && (addr & 0xfc) != 0x30)
return -1;
- down(&amd756_lock);
+ mutex_lock(&amd756_lock);
if (last_channels != channels) {
union i2c_smbus_data mplxdata;
@@ -105,7 +106,7 @@ static inline s32 amd756_access_channel(struct i2c_adapter * adap, u16 addr,
command, size, data);
UNLOCK:
- up(&amd756_lock);
+ mutex_unlock(&amd756_lock);
return error;
}
@@ -166,8 +167,6 @@ static int __init amd756_s4882_init(void)
}
printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4882\n");
- init_MUTEX(&amd756_lock);
-
/* Define the 5 virtual adapters and algorithms structures */
if (!(s4882_adapter = kzalloc(5 * sizeof(struct i2c_adapter),
GFP_KERNEL))) {
diff --git a/drivers/i2c/busses/i2c-frodo.c b/drivers/i2c/busses/i2c-frodo.c
deleted file mode 100644
index b6f52f5a4138..000000000000
--- a/drivers/i2c/busses/i2c-frodo.c
+++ /dev/null
@@ -1,85 +0,0 @@
-
-/*
- * linux/drivers/i2c/i2c-frodo.c
- *
- * Author: Abraham van der Merwe <abraham@2d3d.co.za>
- *
- * An I2C adapter driver for the 2d3D, Inc. StrongARM SA-1110
- * Development board (Frodo).
- *
- * This source code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <asm/hardware.h>
-
-
-static void frodo_setsda (void *data,int state)
-{
- if (state)
- FRODO_CPLD_I2C |= FRODO_I2C_SDA_OUT;
- else
- FRODO_CPLD_I2C &= ~FRODO_I2C_SDA_OUT;
-}
-
-static void frodo_setscl (void *data,int state)
-{
- if (state)
- FRODO_CPLD_I2C |= FRODO_I2C_SCL_OUT;
- else
- FRODO_CPLD_I2C &= ~FRODO_I2C_SCL_OUT;
-}
-
-static int frodo_getsda (void *data)
-{
- return ((FRODO_CPLD_I2C & FRODO_I2C_SDA_IN) != 0);
-}
-
-static int frodo_getscl (void *data)
-{
- return ((FRODO_CPLD_I2C & FRODO_I2C_SCL_IN) != 0);
-}
-
-static struct i2c_algo_bit_data bit_frodo_data = {
- .setsda = frodo_setsda,
- .setscl = frodo_setscl,
- .getsda = frodo_getsda,
- .getscl = frodo_getscl,
- .udelay = 80,
- .mdelay = 80,
- .timeout = HZ
-};
-
-static struct i2c_adapter frodo_ops = {
- .owner = THIS_MODULE,
- .id = I2C_HW_B_FRODO,
- .algo_data = &bit_frodo_data,
- .dev = {
- .name = "Frodo adapter driver",
- },
-};
-
-static int __init i2c_frodo_init (void)
-{
- return i2c_bit_add_bus(&frodo_ops);
-}
-
-static void __exit i2c_frodo_exit (void)
-{
- i2c_bit_del_bus(&frodo_ops);
-}
-
-MODULE_AUTHOR ("Abraham van der Merwe <abraham@2d3d.co.za>");
-MODULE_DESCRIPTION ("I2C-Bus adapter routines for Frodo");
-MODULE_LICENSE ("GPL");
-
-module_init (i2c_frodo_init);
-module_exit (i2c_frodo_exit);
-
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index 1414851a17b8..d00a02fc23e4 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -434,7 +434,7 @@ static int
iop3xx_i2c_probe(struct platform_device *pdev)
{
struct resource *res;
- int ret;
+ int ret, irq;
struct i2c_adapter *new_adapter;
struct i2c_algo_iop3xx_data *adapter_data;
@@ -470,7 +470,12 @@ iop3xx_i2c_probe(struct platform_device *pdev)
goto release_region;
}
- ret = request_irq(platform_get_irq(pdev, 0), iop3xx_i2c_irq_handler, 0,
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ ret = -ENXIO;
+ goto unmap;
+ }
+ ret = request_irq(irq, iop3xx_i2c_irq_handler, 0,
pdev->name, adapter_data);
if (ret) {
diff --git a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c
index 4344ae6b1fcb..c3e1d3e888d7 100644
--- a/drivers/i2c/busses/i2c-isa.c
+++ b/drivers/i2c/busses/i2c-isa.c
@@ -125,7 +125,7 @@ int i2c_isa_del_driver(struct i2c_driver *driver)
static int __init i2c_isa_init(void)
{
- init_MUTEX(&isa_adapter.clist_lock);
+ mutex_init(&isa_adapter.clist_lock);
INIT_LIST_HEAD(&isa_adapter.clients);
isa_adapter.nr = ANY_I2C_ISA_BUS;
diff --git a/drivers/i2c/busses/i2c-ite.c b/drivers/i2c/busses/i2c-ite.c
index 5f5d2944808b..d82e6dae8407 100644
--- a/drivers/i2c/busses/i2c-ite.c
+++ b/drivers/i2c/busses/i2c-ite.c
@@ -200,9 +200,7 @@ static struct i2c_adapter iic_ite_ops = {
.owner = THIS_MODULE,
.id = I2C_HW_I_IIC,
.algo_data = &iic_ite_data,
- .dev = {
- .name = "ITE IIC adapter",
- },
+ .name = "ITE IIC adapter",
};
/* Called when the module is loaded. This function starts the
diff --git a/drivers/i2c/busses/i2c-ixp4xx.c b/drivers/i2c/busses/i2c-ixp4xx.c
index e422d8b2d4d6..2ed07112d683 100644
--- a/drivers/i2c/busses/i2c-ixp4xx.c
+++ b/drivers/i2c/busses/i2c-ixp4xx.c
@@ -126,6 +126,7 @@ static int ixp4xx_i2c_probe(struct platform_device *plat_dev)
drv_data->algo_data.timeout = 100;
drv_data->adapter.id = I2C_HW_B_IXP4XX;
+ drv_data->adapter.class = I2C_CLASS_HWMON;
strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name,
I2C_NAME_SIZE);
drv_data->adapter.algo_data = &drv_data->algo_data;
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 5ccd338a9dc9..2721e4c8184a 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -302,6 +302,10 @@ static int fsl_i2c_probe(struct platform_device *pdev)
}
i2c->irq = platform_get_irq(pdev, 0);
+ if (i2c->irq < 0) {
+ result = -ENXIO;
+ goto fail_get_irq;
+ }
i2c->flags = pdata->device_flags;
init_waitqueue_head(&i2c->queue);
@@ -340,6 +344,7 @@ static int fsl_i2c_probe(struct platform_device *pdev)
fail_irq:
iounmap(i2c->base);
fail_map:
+ fail_get_irq:
kfree(i2c);
return result;
};
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 22781d84f79f..ac5cde1bbd2b 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -516,6 +516,10 @@ mv64xxx_i2c_probe(struct platform_device *pd)
drv_data->freq_m = pdata->freq_m;
drv_data->freq_n = pdata->freq_n;
drv_data->irq = platform_get_irq(pd, 0);
+ if (drv_data->irq < 0) {
+ rc = -ENXIO;
+ goto exit_unmap_regs;
+ }
drv_data->adapter.id = I2C_HW_MV64XXX;
drv_data->adapter.algo = &mv64xxx_i2c_algo;
drv_data->adapter.owner = THIS_MODULE;
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 692f47345481..d9c7c00e71f9 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -22,7 +22,7 @@
/*
Supports:
Intel PIIX4, 440MX
- Serverworks OSB4, CSB5, CSB6
+ Serverworks OSB4, CSB5, CSB6, HT-1000
SMSC Victory66
Note: we assume there can only be one device, with one SMBus interface.
@@ -419,6 +419,8 @@ static struct pci_device_id piix4_ids[] = {
.driver_data = 0 },
{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6),
.driver_data = 0 },
+ { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000SB),
+ .driver_data = 0 },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3),
.driver_data = 3 },
{ PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3),
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index 7579f4b256a8..5155010b455e 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -647,7 +647,7 @@ static inline void i2c_pxa_start_message(struct pxa_i2c *i2c)
}
/*
- * We are protected by the adapter bus semaphore.
+ * We are protected by the adapter bus mutex.
*/
static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num)
{
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index d3478e084522..8bd305e47f0d 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -1,27 +1,26 @@
-/* linux/drivers/i2c/scx200_acb.c
-
+/*
Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
National Semiconductor SCx200 ACCESS.bus support
-
+ Also supports the AMD CS5535 and AMD CS5536
+
Based on i2c-keywest.c which is:
Copyright (c) 2001 Benjamin Herrenschmidt <benh@kernel.crashing.org>
Copyright (c) 2000 Philip Edelbrock <phil@stimpy.netroedge.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.
-
*/
#include <linux/module.h>
@@ -32,7 +31,9 @@
#include <linux/smp_lock.h>
#include <linux/pci.h>
#include <linux/delay.h>
+#include <linux/mutex.h>
#include <asm/io.h>
+#include <asm/msr.h>
#include <linux/scx200.h>
@@ -47,16 +48,7 @@ static int base[MAX_DEVICES] = { 0x820, 0x840 };
module_param_array(base, int, NULL, 0);
MODULE_PARM_DESC(base, "Base addresses for the ACCESS.bus controllers");
-#ifdef DEBUG
-#define DBG(x...) printk(KERN_DEBUG NAME ": " x)
-#else
-#define DBG(x...)
-#endif
-
-/* The hardware supports interrupt driven mode too, but I haven't
- implemented that. */
-#define POLLED_MODE 1
-#define POLL_TIMEOUT (HZ)
+#define POLL_TIMEOUT (HZ/5)
enum scx200_acb_state {
state_idle,
@@ -79,12 +71,11 @@ static const char *scx200_acb_state_name[] = {
};
/* Physical interface */
-struct scx200_acb_iface
-{
+struct scx200_acb_iface {
struct scx200_acb_iface *next;
struct i2c_adapter adapter;
unsigned base;
- struct semaphore sem;
+ struct mutex mutex;
/* State machine data */
enum scx200_acb_state state;
@@ -100,7 +91,7 @@ struct scx200_acb_iface
#define ACBSDA (iface->base + 0)
#define ACBST (iface->base + 1)
#define ACBST_SDAST 0x40 /* SDA Status */
-#define ACBST_BER 0x20
+#define ACBST_BER 0x20
#define ACBST_NEGACK 0x10 /* Negative Acknowledge */
#define ACBST_STASTR 0x08 /* Stall After Start */
#define ACBST_MASTER 0x02
@@ -109,9 +100,9 @@ struct scx200_acb_iface
#define ACBCTL1 (iface->base + 3)
#define ACBCTL1_STASTRE 0x80
#define ACBCTL1_NMINTE 0x40
-#define ACBCTL1_ACK 0x10
-#define ACBCTL1_STOP 0x02
-#define ACBCTL1_START 0x01
+#define ACBCTL1_ACK 0x10
+#define ACBCTL1_STOP 0x02
+#define ACBCTL1_START 0x01
#define ACBADDR (iface->base + 4)
#define ACBCTL2 (iface->base + 5)
#define ACBCTL2_ENABLE 0x01
@@ -122,8 +113,8 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status)
{
const char *errmsg;
- DBG("state %s, status = 0x%02x\n",
- scx200_acb_state_name[iface->state], status);
+ dev_dbg(&iface->adapter.dev, "state %s, status = 0x%02x\n",
+ scx200_acb_state_name[iface->state], status);
if (status & ACBST_BER) {
errmsg = "bus error";
@@ -133,8 +124,17 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status)
errmsg = "not master";
goto error;
}
- if (status & ACBST_NEGACK)
- goto negack;
+ if (status & ACBST_NEGACK) {
+ dev_dbg(&iface->adapter.dev, "negative ack in state %s\n",
+ scx200_acb_state_name[iface->state]);
+
+ iface->state = state_idle;
+ iface->result = -ENXIO;
+
+ outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1);
+ outb(ACBST_STASTR | ACBST_NEGACK, ACBST);
+ return;
+ }
switch (iface->state) {
case state_idle:
@@ -160,10 +160,10 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status)
case state_repeat_start:
outb(inb(ACBCTL1) | ACBCTL1_START, ACBCTL1);
/* fallthrough */
-
+
case state_quick:
if (iface->address_byte & 1) {
- if (iface->len == 1)
+ if (iface->len == 1)
outb(inb(ACBCTL1) | ACBCTL1_ACK, ACBCTL1);
else
outb(inb(ACBCTL1) & ~ACBCTL1_ACK, ACBCTL1);
@@ -202,26 +202,15 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status)
outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1);
break;
}
-
+
outb(*iface->ptr++, ACBSDA);
--iface->len;
-
+
break;
}
return;
- negack:
- DBG("negative acknowledge in state %s\n",
- scx200_acb_state_name[iface->state]);
-
- iface->state = state_idle;
- iface->result = -ENXIO;
-
- outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1);
- outb(ACBST_STASTR | ACBST_NEGACK, ACBST);
- return;
-
error:
dev_err(&iface->adapter.dev, "%s in state %s\n", errmsg,
scx200_acb_state_name[iface->state]);
@@ -231,20 +220,9 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status)
iface->needs_reset = 1;
}
-static void scx200_acb_timeout(struct scx200_acb_iface *iface)
-{
- dev_err(&iface->adapter.dev, "timeout in state %s\n",
- scx200_acb_state_name[iface->state]);
-
- iface->state = state_idle;
- iface->result = -EIO;
- iface->needs_reset = 1;
-}
-
-#ifdef POLLED_MODE
static void scx200_acb_poll(struct scx200_acb_iface *iface)
{
- u8 status = 0;
+ u8 status;
unsigned long timeout;
timeout = jiffies + POLL_TIMEOUT;
@@ -254,17 +232,21 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface)
scx200_acb_machine(iface, status);
return;
}
- msleep(10);
+ yield();
}
- scx200_acb_timeout(iface);
+ dev_err(&iface->adapter.dev, "timeout in state %s\n",
+ scx200_acb_state_name[iface->state]);
+
+ iface->state = state_idle;
+ iface->result = -EIO;
+ iface->needs_reset = 1;
}
-#endif /* POLLED_MODE */
static void scx200_acb_reset(struct scx200_acb_iface *iface)
{
/* Disable the ACCESS.bus device and Configure the SCL
- frequency: 16 clock cycles */
+ frequency: 16 clock cycles */
outb(0x70, ACBCTL2);
/* Polling mode */
outb(0, ACBCTL1);
@@ -283,9 +265,9 @@ static void scx200_acb_reset(struct scx200_acb_iface *iface)
}
static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter,
- u16 address, unsigned short flags,
- char rw, u8 command, int size,
- union i2c_smbus_data *data)
+ u16 address, unsigned short flags,
+ char rw, u8 command, int size,
+ union i2c_smbus_data *data)
{
struct scx200_acb_iface *iface = i2c_get_adapdata(adapter);
int len;
@@ -295,53 +277,47 @@ static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter,
switch (size) {
case I2C_SMBUS_QUICK:
- len = 0;
- buffer = NULL;
- break;
+ len = 0;
+ buffer = NULL;
+ break;
+
case I2C_SMBUS_BYTE:
- if (rw == I2C_SMBUS_READ) {
- len = 1;
- buffer = &data->byte;
- } else {
- len = 1;
- buffer = &command;
- }
- break;
+ len = 1;
+ buffer = rw ? &data->byte : &command;
+ break;
+
case I2C_SMBUS_BYTE_DATA:
- len = 1;
- buffer = &data->byte;
- break;
+ len = 1;
+ buffer = &data->byte;
+ break;
+
case I2C_SMBUS_WORD_DATA:
len = 2;
- cur_word = cpu_to_le16(data->word);
- buffer = (u8 *)&cur_word;
+ cur_word = cpu_to_le16(data->word);
+ buffer = (u8 *)&cur_word;
break;
+
case I2C_SMBUS_BLOCK_DATA:
- len = data->block[0];
- buffer = &data->block[1];
+ len = data->block[0];
+ buffer = &data->block[1];
break;
+
default:
- return -EINVAL;
+ return -EINVAL;
}
- DBG("size=%d, address=0x%x, command=0x%x, len=%d, read=%d\n",
- size, address, command, len, rw == I2C_SMBUS_READ);
+ dev_dbg(&adapter->dev,
+ "size=%d, address=0x%x, command=0x%x, len=%d, read=%d\n",
+ size, address, command, len, rw);
if (!len && rw == I2C_SMBUS_READ) {
- dev_warn(&adapter->dev, "zero length read\n");
+ dev_dbg(&adapter->dev, "zero length read\n");
return -EINVAL;
}
- if (len && !buffer) {
- dev_warn(&adapter->dev, "nonzero length but no buffer\n");
- return -EFAULT;
- }
-
- down(&iface->sem);
+ mutex_lock(&iface->mutex);
- iface->address_byte = address<<1;
- if (rw == I2C_SMBUS_READ)
- iface->address_byte |= 1;
+ iface->address_byte = (address << 1) | rw;
iface->command = command;
iface->ptr = buffer;
iface->len = len;
@@ -355,25 +331,21 @@ static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter,
else
iface->state = state_address;
-#ifdef POLLED_MODE
while (iface->state != state_idle)
scx200_acb_poll(iface);
-#else /* POLLED_MODE */
-#error Interrupt driven mode not implemented
-#endif /* POLLED_MODE */
if (iface->needs_reset)
scx200_acb_reset(iface);
rc = iface->result;
- up(&iface->sem);
+ mutex_unlock(&iface->mutex);
if (rc == 0 && size == I2C_SMBUS_WORD_DATA && rw == I2C_SMBUS_READ)
- data->word = le16_to_cpu(cur_word);
+ data->word = le16_to_cpu(cur_word);
#ifdef DEBUG
- DBG(": transfer done, result: %d", rc);
+ dev_dbg(&adapter->dev, "transfer done, result: %d", rc);
if (buffer) {
int i;
printk(" data:");
@@ -400,17 +372,18 @@ static struct i2c_algorithm scx200_acb_algorithm = {
};
static struct scx200_acb_iface *scx200_acb_list;
+static DECLARE_MUTEX(scx200_acb_list_mutex);
static int scx200_acb_probe(struct scx200_acb_iface *iface)
{
u8 val;
/* Disable the ACCESS.bus device and Configure the SCL
- frequency: 16 clock cycles */
+ frequency: 16 clock cycles */
outb(0x70, ACBCTL2);
if (inb(ACBCTL2) != 0x70) {
- DBG("ACBCTL2 readback failed\n");
+ pr_debug(NAME ": ACBCTL2 readback failed\n");
return -ENXIO;
}
@@ -418,7 +391,8 @@ static int scx200_acb_probe(struct scx200_acb_iface *iface)
val = inb(ACBCTL1);
if (val) {
- DBG("disabled, but ACBCTL1=0x%02x\n", val);
+ pr_debug(NAME ": disabled, but ACBCTL1=0x%02x\n",
+ val);
return -ENXIO;
}
@@ -428,18 +402,19 @@ static int scx200_acb_probe(struct scx200_acb_iface *iface)
val = inb(ACBCTL1);
if ((val & ACBCTL1_NMINTE) != ACBCTL1_NMINTE) {
- DBG("enabled, but NMINTE won't be set, ACBCTL1=0x%02x\n", val);
+ pr_debug(NAME ": enabled, but NMINTE won't be set, "
+ "ACBCTL1=0x%02x\n", val);
return -ENXIO;
}
return 0;
}
-static int __init scx200_acb_create(int base, int index)
+static int __init scx200_acb_create(const char *text, int base, int index)
{
struct scx200_acb_iface *iface;
struct i2c_adapter *adapter;
- int rc = 0;
+ int rc;
char description[64];
iface = kzalloc(sizeof(*iface), GFP_KERNEL);
@@ -451,50 +426,51 @@ static int __init scx200_acb_create(int base, int index)
adapter = &iface->adapter;
i2c_set_adapdata(adapter, iface);
- snprintf(adapter->name, I2C_NAME_SIZE, "SCx200 ACB%d", index);
+ snprintf(adapter->name, I2C_NAME_SIZE, "%s ACB%d", text, index);
adapter->owner = THIS_MODULE;
adapter->id = I2C_HW_SMBUS_SCX200;
adapter->algo = &scx200_acb_algorithm;
adapter->class = I2C_CLASS_HWMON;
- init_MUTEX(&iface->sem);
+ mutex_init(&iface->mutex);
+
+ snprintf(description, sizeof(description), "%s ACCESS.bus [%s]",
+ text, adapter->name);
- snprintf(description, sizeof(description), "NatSemi SCx200 ACCESS.bus [%s]", adapter->name);
if (request_region(base, 8, description) == 0) {
- dev_err(&adapter->dev, "can't allocate io 0x%x-0x%x\n",
+ printk(KERN_ERR NAME ": can't allocate io 0x%x-0x%x\n",
base, base + 8-1);
rc = -EBUSY;
- goto errout;
+ goto errout_free;
}
iface->base = base;
rc = scx200_acb_probe(iface);
if (rc) {
- dev_warn(&adapter->dev, "probe failed\n");
- goto errout;
+ printk(KERN_WARNING NAME ": probe failed\n");
+ goto errout_release;
}
scx200_acb_reset(iface);
if (i2c_add_adapter(adapter) < 0) {
- dev_err(&adapter->dev, "failed to register\n");
+ printk(KERN_ERR NAME ": failed to register\n");
rc = -ENODEV;
- goto errout;
+ goto errout_release;
}
- lock_kernel();
+ down(&scx200_acb_list_mutex);
iface->next = scx200_acb_list;
scx200_acb_list = iface;
- unlock_kernel();
+ up(&scx200_acb_list_mutex);
return 0;
+ errout_release:
+ release_region(iface->base, 8);
+ errout_free:
+ kfree(iface);
errout:
- if (iface) {
- if (iface->base)
- release_region(iface->base, 8);
- kfree(iface);
- }
return rc;
}
@@ -504,50 +480,69 @@ static struct pci_device_id scx200[] = {
{ },
};
+static struct pci_device_id divil_pci[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
+ { } /* NULL entry */
+};
+
+#define MSR_LBAR_SMB 0x5140000B
+
+static int scx200_add_cs553x(void)
+{
+ u32 low, hi;
+ u32 smb_base;
+
+ /* Grab & reserve the SMB I/O range */
+ rdmsr(MSR_LBAR_SMB, low, hi);
+
+ /* Check the IO mask and whether SMB is enabled */
+ if (hi != 0x0000F001) {
+ printk(KERN_WARNING NAME ": SMBus not enabled\n");
+ return -ENODEV;
+ }
+
+ /* SMBus IO size is 8 bytes */
+ smb_base = low & 0x0000FFF8;
+
+ return scx200_acb_create("CS5535", smb_base, 0);
+}
+
static int __init scx200_acb_init(void)
{
int i;
- int rc;
+ int rc = -ENODEV;
pr_debug(NAME ": NatSemi SCx200 ACCESS.bus Driver\n");
/* Verify that this really is a SCx200 processor */
- if (pci_dev_present(scx200) == 0)
- return -ENODEV;
+ if (pci_dev_present(scx200)) {
+ for (i = 0; i < MAX_DEVICES; ++i) {
+ if (base[i] > 0)
+ rc = scx200_acb_create("SCx200", base[i], i);
+ }
+ } else if (pci_dev_present(divil_pci))
+ rc = scx200_add_cs553x();
- rc = -ENXIO;
- for (i = 0; i < MAX_DEVICES; ++i) {
- if (base[i] > 0)
- rc = scx200_acb_create(base[i], i);
- }
- if (scx200_acb_list)
- return 0;
return rc;
}
static void __exit scx200_acb_cleanup(void)
{
struct scx200_acb_iface *iface;
- lock_kernel();
+
+ down(&scx200_acb_list_mutex);
while ((iface = scx200_acb_list) != NULL) {
scx200_acb_list = iface->next;
- unlock_kernel();
+ up(&scx200_acb_list_mutex);
i2c_del_adapter(&iface->adapter);
release_region(iface->base, 8);
kfree(iface);
- lock_kernel();
+ down(&scx200_acb_list_mutex);
}
- unlock_kernel();
+ up(&scx200_acb_list_mutex);
}
module_init(scx200_acb_init);
module_exit(scx200_acb_cleanup);
-
-/*
- Local variables:
- compile-command: "make -k -C ../.. SUBDIRS=drivers/i2c modules"
- c-basic-offset: 8
- End:
-*/
-
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index f9fae28f5612..7aa5c38f0855 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -65,15 +65,6 @@ config SENSORS_PCF8591
This driver can also be built as a module. If so, the module
will be called pcf8591.
-config SENSORS_RTC8564
- tristate "Epson 8564 RTC chip"
- depends on I2C && EXPERIMENTAL
- help
- If you say yes here you get support for the Epson 8564 RTC chip.
-
- This driver can also be built as a module. If so, the module
- will be called i2c-rtc8564.
-
config ISP1301_OMAP
tristate "Philips ISP1301 with OMAP OTG"
depends on I2C && ARCH_OMAP_OTG
@@ -126,13 +117,4 @@ config SENSORS_MAX6875
This driver can also be built as a module. If so, the module
will be called max6875.
-config RTC_X1205_I2C
- tristate "Xicor X1205 RTC chip"
- depends on I2C && EXPERIMENTAL
- help
- If you say yes here you get support for the Xicor X1205 RTC chip.
-
- This driver can also be built as a module. If so, the module
- will be called x1205.
-
endmenu
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index 46178b57b1f1..779868ef2e26 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -10,10 +10,8 @@ obj-$(CONFIG_SENSORS_M41T00) += m41t00.o
obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o
obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
-obj-$(CONFIG_SENSORS_RTC8564) += rtc8564.o
obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
obj-$(CONFIG_TPS65010) += tps65010.o
-obj-$(CONFIG_RTC_X1205_I2C) += x1205.o
ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/chips/ds1374.c b/drivers/i2c/chips/ds1374.c
index 0710b9da9d54..03d09ed5ec2c 100644
--- a/drivers/i2c/chips/ds1374.c
+++ b/drivers/i2c/chips/ds1374.c
@@ -26,6 +26,7 @@
#include <linux/i2c.h>
#include <linux/rtc.h>
#include <linux/bcd.h>
+#include <linux/mutex.h>
#define DS1374_REG_TOD0 0x00
#define DS1374_REG_TOD1 0x01
@@ -41,7 +42,7 @@
#define DS1374_DRV_NAME "ds1374"
-static DECLARE_MUTEX(ds1374_mutex);
+static DEFINE_MUTEX(ds1374_mutex);
static struct i2c_driver ds1374_driver;
static struct i2c_client *save_client;
@@ -114,7 +115,7 @@ ulong ds1374_get_rtc_time(void)
ulong t1, t2;
int limit = 10; /* arbitrary retry limit */
- down(&ds1374_mutex);
+ mutex_lock(&ds1374_mutex);
/*
* Since the reads are being performed one byte at a time using
@@ -127,7 +128,7 @@ ulong ds1374_get_rtc_time(void)
t2 = ds1374_read_rtc();
} while (t1 != t2 && limit--);
- up(&ds1374_mutex);
+ mutex_unlock(&ds1374_mutex);
if (t1 != t2) {
dev_warn(&save_client->dev,
@@ -145,7 +146,7 @@ static void ds1374_set_tlet(ulong arg)
t1 = *(ulong *) arg;
- down(&ds1374_mutex);
+ mutex_lock(&ds1374_mutex);
/*
* Since the writes are being performed one byte at a time using
@@ -158,7 +159,7 @@ static void ds1374_set_tlet(ulong arg)
t2 = ds1374_read_rtc();
} while (t1 != t2 && limit--);
- up(&ds1374_mutex);
+ mutex_unlock(&ds1374_mutex);
if (t1 != t2)
dev_warn(&save_client->dev,
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
index 41116b7947f6..13c108269a6d 100644
--- a/drivers/i2c/chips/eeprom.c
+++ b/drivers/i2c/chips/eeprom.c
@@ -33,6 +33,7 @@
#include <linux/sched.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
+#include <linux/mutex.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54,
@@ -54,7 +55,7 @@ enum eeprom_nature {
/* Each client has this additional data */
struct eeprom_data {
struct i2c_client client;
- struct semaphore update_lock;
+ struct mutex update_lock;
u8 valid; /* bitfield, bit!=0 if slice is valid */
unsigned long last_updated[8]; /* In jiffies, 8 slices */
u8 data[EEPROM_SIZE]; /* Register values */
@@ -81,7 +82,7 @@ static void eeprom_update_client(struct i2c_client *client, u8 slice)
struct eeprom_data *data = i2c_get_clientdata(client);
int i, j;
- down(&data->update_lock);
+ mutex_lock(&data->update_lock);
if (!(data->valid & (1 << slice)) ||
time_after(jiffies, data->last_updated[slice] + 300 * HZ)) {
@@ -107,7 +108,7 @@ static void eeprom_update_client(struct i2c_client *client, u8 slice)
data->valid |= (1 << slice);
}
exit:
- up(&data->update_lock);
+ mutex_unlock(&data->update_lock);
}
static ssize_t eeprom_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
@@ -187,7 +188,7 @@ static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
/* Fill in the remaining client fields */
strlcpy(new_client->name, "eeprom", I2C_NAME_SIZE);
data->valid = 0;
- init_MUTEX(&data->update_lock);
+ mutex_init(&data->update_lock);
data->nature = UNKNOWN;
/* Tell the I2C layer a new client has arrived */
diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c
index 1251c7fc18d5..e6f1ab7b913c 100644
--- a/drivers/i2c/chips/isp1301_omap.c
+++ b/drivers/i2c/chips/isp1301_omap.c
@@ -1635,8 +1635,6 @@ static struct i2c_driver isp1301_driver = {
.driver = {
.name = "isp1301_omap",
},
- .id = 1301, /* FIXME "official", i2c-ids.h */
- .class = I2C_CLASS_HWMON,
.attach_adapter = isp1301_scan_bus,
.detach_client = isp1301_detach_client,
};
diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c
index 2dc3d48375fc..b5aabe7cf792 100644
--- a/drivers/i2c/chips/m41t00.c
+++ b/drivers/i2c/chips/m41t00.c
@@ -24,13 +24,14 @@
#include <linux/i2c.h>
#include <linux/rtc.h>
#include <linux/bcd.h>
+#include <linux/mutex.h>
#include <asm/time.h>
#include <asm/rtc.h>
#define M41T00_DRV_NAME "m41t00"
-static DECLARE_MUTEX(m41t00_mutex);
+static DEFINE_MUTEX(m41t00_mutex);
static struct i2c_driver m41t00_driver;
static struct i2c_client *save_client;
@@ -54,7 +55,7 @@ m41t00_get_rtc_time(void)
sec = min = hour = day = mon = year = 0;
sec1 = min1 = hour1 = day1 = mon1 = year1 = 0;
- down(&m41t00_mutex);
+ mutex_lock(&m41t00_mutex);
do {
if (((sec = i2c_smbus_read_byte_data(save_client, 0)) >= 0)
&& ((min = i2c_smbus_read_byte_data(save_client, 1))
@@ -80,7 +81,7 @@ m41t00_get_rtc_time(void)
mon1 = mon;
year1 = year;
} while (--limit > 0);
- up(&m41t00_mutex);
+ mutex_unlock(&m41t00_mutex);
if (limit == 0) {
dev_warn(&save_client->dev,
@@ -125,7 +126,7 @@ m41t00_set_tlet(ulong arg)
BIN_TO_BCD(tm.tm_mday);
BIN_TO_BCD(tm.tm_year);
- down(&m41t00_mutex);
+ mutex_lock(&m41t00_mutex);
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)
@@ -140,7 +141,7 @@ m41t00_set_tlet(ulong arg)
dev_warn(&save_client->dev,"m41t00: can't write to rtc chip\n");
- up(&m41t00_mutex);
+ mutex_unlock(&m41t00_mutex);
return;
}
diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c
index 6d3ff584155e..88d2ddee4490 100644
--- a/drivers/i2c/chips/max6875.c
+++ b/drivers/i2c/chips/max6875.c
@@ -31,7 +31,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/i2c.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
/* Do not scan - the MAX6875 access method will write to some EEPROM chips */
static unsigned short normal_i2c[] = {I2C_CLIENT_END};
@@ -54,7 +54,7 @@ I2C_CLIENT_INSMOD_1(max6875);
/* Each client has this additional data */
struct max6875_data {
struct i2c_client client;
- struct semaphore update_lock;
+ struct mutex update_lock;
u32 valid;
u8 data[USER_EEPROM_SIZE];
@@ -83,7 +83,7 @@ static void max6875_update_slice(struct i2c_client *client, int slice)
if (slice >= USER_EEPROM_SLICES)
return;
- down(&data->update_lock);
+ mutex_lock(&data->update_lock);
buf = &data->data[slice << SLICE_BITS];
@@ -122,7 +122,7 @@ static void max6875_update_slice(struct i2c_client *client, int slice)
data->valid |= (1 << slice);
}
exit_up:
- up(&data->update_lock);
+ mutex_unlock(&data->update_lock);
}
static ssize_t max6875_read(struct kobject *kobj, char *buf, loff_t off,
@@ -196,7 +196,7 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
real_client->driver = &max6875_driver;
real_client->flags = 0;
strlcpy(real_client->name, "max6875", I2C_NAME_SIZE);
- init_MUTEX(&data->update_lock);
+ mutex_init(&data->update_lock);
/* Init fake client data */
/* set the client data to the i2c_client so that it will get freed */
diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c
index 36cff09c678d..925a6b371fd2 100644
--- a/drivers/i2c/chips/pcf8591.c
+++ b/drivers/i2c/chips/pcf8591.c
@@ -24,6 +24,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
+#include <linux/mutex.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
@@ -74,7 +75,7 @@ MODULE_PARM_DESC(input_mode,
struct pcf8591_data {
struct i2c_client client;
- struct semaphore update_lock;
+ struct mutex update_lock;
u8 control;
u8 aout;
@@ -144,13 +145,13 @@ static ssize_t set_out0_enable(struct device *dev, struct device_attribute *attr
struct pcf8591_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10);
- down(&data->update_lock);
+ mutex_lock(&data->update_lock);
if (val)
data->control |= PCF8591_CONTROL_AOEF;
else
data->control &= ~PCF8591_CONTROL_AOEF;
i2c_smbus_write_byte(client, data->control);
- up(&data->update_lock);
+ mutex_unlock(&data->update_lock);
return count;
}
@@ -200,7 +201,7 @@ static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
/* Fill in the remaining client fields and put it into the global
list */
strlcpy(new_client->name, "pcf8591", I2C_NAME_SIZE);
- init_MUTEX(&data->update_lock);
+ mutex_init(&data->update_lock);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
@@ -265,7 +266,7 @@ static int pcf8591_read_channel(struct device *dev, int channel)
struct i2c_client *client = to_i2c_client(dev);
struct pcf8591_data *data = i2c_get_clientdata(client);
- down(&data->update_lock);
+ mutex_lock(&data->update_lock);
if ((data->control & PCF8591_CONTROL_AICH_MASK) != channel) {
data->control = (data->control & ~PCF8591_CONTROL_AICH_MASK)
@@ -278,7 +279,7 @@ static int pcf8591_read_channel(struct device *dev, int channel)
}
value = i2c_smbus_read_byte(client);
- up(&data->update_lock);
+ mutex_unlock(&data->update_lock);
if ((channel == 2 && input_mode == 2) ||
(channel != 3 && (input_mode == 1 || input_mode == 3)))
diff --git a/drivers/i2c/chips/rtc8564.c b/drivers/i2c/chips/rtc8564.c
deleted file mode 100644
index ceaa6b0bdfd6..000000000000
--- a/drivers/i2c/chips/rtc8564.c
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
- * linux/drivers/i2c/chips/rtc8564.c
- *
- * Copyright (C) 2002-2004 Stefan Eletzhofer
- *
- * based on linux/drivers/acron/char/pcf8583.c
- * Copyright (C) 2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Driver for system3's EPSON RTC 8564 chip
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/bcd.h>
-#include <linux/i2c.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/rtc.h> /* get the user-level API */
-#include <linux/init.h>
-
-#include "rtc8564.h"
-
-#ifdef DEBUG
-# define _DBG(x, fmt, args...) do{ if (debug>=x) printk(KERN_DEBUG"%s: " fmt "\n", __FUNCTION__, ##args); } while(0);
-#else
-# define _DBG(x, fmt, args...) do { } while(0);
-#endif
-
-#define _DBGRTCTM(x, rtctm) if (debug>=x) printk("%s: secs=%d, mins=%d, hours=%d, mday=%d, " \
- "mon=%d, year=%d, wday=%d VL=%d\n", __FUNCTION__, \
- (rtctm).secs, (rtctm).mins, (rtctm).hours, (rtctm).mday, \
- (rtctm).mon, (rtctm).year, (rtctm).wday, (rtctm).vl);
-
-struct rtc8564_data {
- struct i2c_client client;
- u16 ctrl;
-};
-
-static inline u8 _rtc8564_ctrl1(struct i2c_client *client)
-{
- struct rtc8564_data *data = i2c_get_clientdata(client);
- return data->ctrl & 0xff;
-}
-static inline u8 _rtc8564_ctrl2(struct i2c_client *client)
-{
- struct rtc8564_data *data = i2c_get_clientdata(client);
- return (data->ctrl & 0xff00) >> 8;
-}
-
-#define CTRL1(c) _rtc8564_ctrl1(c)
-#define CTRL2(c) _rtc8564_ctrl2(c)
-
-static int debug;;
-module_param(debug, int, S_IRUGO | S_IWUSR);
-
-static struct i2c_driver rtc8564_driver;
-
-static unsigned short ignore[] = { I2C_CLIENT_END };
-static unsigned short normal_addr[] = { 0x51, I2C_CLIENT_END };
-
-static struct i2c_client_address_data addr_data = {
- .normal_i2c = normal_addr,
- .probe = ignore,
- .ignore = ignore,
-};
-
-static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem);
-static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem);
-
-static int rtc8564_read(struct i2c_client *client, unsigned char adr,
- unsigned char *buf, unsigned char len)
-{
- int ret = -EIO;
- unsigned char addr[1] = { adr };
- struct i2c_msg msgs[2] = {
- {client->addr, 0, 1, addr},
- {client->addr, I2C_M_RD, len, buf}
- };
-
- _DBG(1, "client=%p, adr=%d, buf=%p, len=%d", client, adr, buf, len);
-
- if (!buf) {
- ret = -EINVAL;
- goto done;
- }
-
- ret = i2c_transfer(client->adapter, msgs, 2);
- if (ret == 2) {
- ret = 0;
- }
-
-done:
- return ret;
-}
-
-static int rtc8564_write(struct i2c_client *client, unsigned char adr,
- unsigned char *data, unsigned char len)
-{
- int ret = 0;
- unsigned char _data[16];
- struct i2c_msg wr;
- int i;
-
- if (!data || len > 15) {
- ret = -EINVAL;
- goto done;
- }
-
- _DBG(1, "client=%p, adr=%d, buf=%p, len=%d", client, adr, data, len);
-
- _data[0] = adr;
- for (i = 0; i < len; i++) {
- _data[i + 1] = data[i];
- _DBG(5, "data[%d] = 0x%02x (%d)", i, data[i], data[i]);
- }
-
- wr.addr = client->addr;
- wr.flags = 0;
- wr.len = len + 1;
- wr.buf = _data;
-
- ret = i2c_transfer(client->adapter, &wr, 1);
- if (ret == 1) {
- ret = 0;
- }
-
-done:
- return ret;
-}
-
-static int rtc8564_attach(struct i2c_adapter *adap, int addr, int kind)
-{
- int ret;
- struct i2c_client *new_client;
- struct rtc8564_data *d;
- unsigned char data[10];
- unsigned char ad[1] = { 0 };
- struct i2c_msg ctrl_wr[1] = {
- {addr, 0, 2, data}
- };
- struct i2c_msg ctrl_rd[2] = {
- {addr, 0, 1, ad},
- {addr, I2C_M_RD, 2, data}
- };
-
- d = kzalloc(sizeof(struct rtc8564_data), GFP_KERNEL);
- if (!d) {
- ret = -ENOMEM;
- goto done;
- }
- new_client = &d->client;
-
- strlcpy(new_client->name, "RTC8564", I2C_NAME_SIZE);
- i2c_set_clientdata(new_client, d);
- new_client->addr = addr;
- new_client->adapter = adap;
- new_client->driver = &rtc8564_driver;
-
- _DBG(1, "client=%p", new_client);
-
- /* init ctrl1 reg */
- data[0] = 0;
- data[1] = 0;
- ret = i2c_transfer(new_client->adapter, ctrl_wr, 1);
- if (ret != 1) {
- printk(KERN_INFO "rtc8564: cant init ctrl1\n");
- ret = -ENODEV;
- goto done;
- }
-
- /* read back ctrl1 and ctrl2 */
- ret = i2c_transfer(new_client->adapter, ctrl_rd, 2);
- if (ret != 2) {
- printk(KERN_INFO "rtc8564: cant read ctrl\n");
- ret = -ENODEV;
- goto done;
- }
-
- d->ctrl = data[0] | (data[1] << 8);
-
- _DBG(1, "RTC8564_REG_CTRL1=%02x, RTC8564_REG_CTRL2=%02x",
- data[0], data[1]);
-
- ret = i2c_attach_client(new_client);
-done:
- if (ret) {
- kfree(d);
- }
- return ret;
-}
-
-static int rtc8564_probe(struct i2c_adapter *adap)
-{
- return i2c_probe(adap, &addr_data, rtc8564_attach);
-}
-
-static int rtc8564_detach(struct i2c_client *client)
-{
- i2c_detach_client(client);
- kfree(i2c_get_clientdata(client));
- return 0;
-}
-
-static int rtc8564_get_datetime(struct i2c_client *client, struct rtc_tm *dt)
-{
- int ret = -EIO;
- unsigned char buf[15];
-
- _DBG(1, "client=%p, dt=%p", client, dt);
-
- if (!dt)
- return -EINVAL;
-
- memset(buf, 0, sizeof(buf));
-
- ret = rtc8564_read(client, 0, buf, 15);
- if (ret)
- return ret;
-
- /* century stored in minute alarm reg */
- dt->year = BCD2BIN(buf[RTC8564_REG_YEAR]);
- dt->year += 100 * BCD2BIN(buf[RTC8564_REG_AL_MIN] & 0x3f);
- dt->mday = BCD2BIN(buf[RTC8564_REG_DAY] & 0x3f);
- dt->wday = BCD2BIN(buf[RTC8564_REG_WDAY] & 7);
- dt->mon = BCD2BIN(buf[RTC8564_REG_MON_CENT] & 0x1f);
-
- dt->secs = BCD2BIN(buf[RTC8564_REG_SEC] & 0x7f);
- dt->vl = (buf[RTC8564_REG_SEC] & 0x80) == 0x80;
- dt->mins = BCD2BIN(buf[RTC8564_REG_MIN] & 0x7f);
- dt->hours = BCD2BIN(buf[RTC8564_REG_HR] & 0x3f);
-
- _DBGRTCTM(2, *dt);
-
- return 0;
-}
-
-static int
-rtc8564_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo)
-{
- int ret, len = 5;
- unsigned char buf[15];
-
- _DBG(1, "client=%p, dt=%p", client, dt);
-
- if (!dt)
- return -EINVAL;
-
- _DBGRTCTM(2, *dt);
-
- buf[RTC8564_REG_CTRL1] = CTRL1(client) | RTC8564_CTRL1_STOP;
- buf[RTC8564_REG_CTRL2] = CTRL2(client);
- buf[RTC8564_REG_SEC] = BIN2BCD(dt->secs);
- buf[RTC8564_REG_MIN] = BIN2BCD(dt->mins);
- buf[RTC8564_REG_HR] = BIN2BCD(dt->hours);
-
- if (datetoo) {
- len += 5;
- buf[RTC8564_REG_DAY] = BIN2BCD(dt->mday);
- buf[RTC8564_REG_WDAY] = BIN2BCD(dt->wday);
- buf[RTC8564_REG_MON_CENT] = BIN2BCD(dt->mon) & 0x1f;
- /* century stored in minute alarm reg */
- buf[RTC8564_REG_YEAR] = BIN2BCD(dt->year % 100);
- buf[RTC8564_REG_AL_MIN] = BIN2BCD(dt->year / 100);
- }
-
- ret = rtc8564_write(client, 0, buf, len);
- if (ret) {
- _DBG(1, "error writing data! %d", ret);
- }
-
- buf[RTC8564_REG_CTRL1] = CTRL1(client);
- ret = rtc8564_write(client, 0, buf, 1);
- if (ret) {
- _DBG(1, "error writing data! %d", ret);
- }
-
- return ret;
-}
-
-static int rtc8564_get_ctrl(struct i2c_client *client, unsigned int *ctrl)
-{
- struct rtc8564_data *data = i2c_get_clientdata(client);
-
- if (!ctrl)
- return -1;
-
- *ctrl = data->ctrl;
- return 0;
-}
-
-static int rtc8564_set_ctrl(struct i2c_client *client, unsigned int *ctrl)
-{
- struct rtc8564_data *data = i2c_get_clientdata(client);
- unsigned char buf[2];
-
- if (!ctrl)
- return -1;
-
- buf[0] = *ctrl & 0xff;
- buf[1] = (*ctrl & 0xff00) >> 8;
- data->ctrl = *ctrl;
-
- return rtc8564_write(client, 0, buf, 2);
-}
-
-static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem)
-{
-
- if (!mem)
- return -EINVAL;
-
- return rtc8564_read(client, mem->loc, mem->data, mem->nr);
-}
-
-static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem)
-{
-
- if (!mem)
- return -EINVAL;
-
- return rtc8564_write(client, mem->loc, mem->data, mem->nr);
-}
-
-static int
-rtc8564_command(struct i2c_client *client, unsigned int cmd, void *arg)
-{
-
- _DBG(1, "cmd=%d", cmd);
-
- switch (cmd) {
- case RTC_GETDATETIME:
- return rtc8564_get_datetime(client, arg);
-
- case RTC_SETTIME:
- return rtc8564_set_datetime(client, arg, 0);
-
- case RTC_SETDATETIME:
- return rtc8564_set_datetime(client, arg, 1);
-
- case RTC_GETCTRL:
- return rtc8564_get_ctrl(client, arg);
-
- case RTC_SETCTRL:
- return rtc8564_set_ctrl(client, arg);
-
- case MEM_READ:
- return rtc8564_read_mem(client, arg);
-
- case MEM_WRITE:
- return rtc8564_write_mem(client, arg);
-
- default:
- return -EINVAL;
- }
-}
-
-static struct i2c_driver rtc8564_driver = {
- .driver = {
- .name = "RTC8564",
- },
- .id = I2C_DRIVERID_RTC8564,
- .attach_adapter = rtc8564_probe,
- .detach_client = rtc8564_detach,
- .command = rtc8564_command
-};
-
-static __init int rtc8564_init(void)
-{
- return i2c_add_driver(&rtc8564_driver);
-}
-
-static __exit void rtc8564_exit(void)
-{
- i2c_del_driver(&rtc8564_driver);
-}
-
-MODULE_AUTHOR("Stefan Eletzhofer <Stefan.Eletzhofer@eletztrick.de>");
-MODULE_DESCRIPTION("EPSON RTC8564 Driver");
-MODULE_LICENSE("GPL");
-
-module_init(rtc8564_init);
-module_exit(rtc8564_exit);
diff --git a/drivers/i2c/chips/rtc8564.h b/drivers/i2c/chips/rtc8564.h
deleted file mode 100644
index e5342d10b8fa..000000000000
--- a/drivers/i2c/chips/rtc8564.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * linux/drivers/i2c/chips/rtc8564.h
- *
- * Copyright (C) 2002-2004 Stefan Eletzhofer
- *
- * based on linux/drivers/acron/char/pcf8583.h
- * Copyright (C) 2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-struct rtc_tm {
- unsigned char secs;
- unsigned char mins;
- unsigned char hours;
- unsigned char mday;
- unsigned char mon;
- unsigned short year; /* xxxx 4 digits :) */
- unsigned char wday;
- unsigned char vl;
-};
-
-struct mem {
- unsigned int loc;
- unsigned int nr;
- unsigned char *data;
-};
-
-#define RTC_GETDATETIME 0
-#define RTC_SETTIME 1
-#define RTC_SETDATETIME 2
-#define RTC_GETCTRL 3
-#define RTC_SETCTRL 4
-#define MEM_READ 5
-#define MEM_WRITE 6
-
-#define RTC8564_REG_CTRL1 0x0 /* T 0 S 0 | T 0 0 0 */
-#define RTC8564_REG_CTRL2 0x1 /* 0 0 0 TI/TP | AF TF AIE TIE */
-#define RTC8564_REG_SEC 0x2 /* VL 4 2 1 | 8 4 2 1 */
-#define RTC8564_REG_MIN 0x3 /* x 4 2 1 | 8 4 2 1 */
-#define RTC8564_REG_HR 0x4 /* x x 2 1 | 8 4 2 1 */
-#define RTC8564_REG_DAY 0x5 /* x x 2 1 | 8 4 2 1 */
-#define RTC8564_REG_WDAY 0x6 /* x x x x | x 4 2 1 */
-#define RTC8564_REG_MON_CENT 0x7 /* C x x 1 | 8 4 2 1 */
-#define RTC8564_REG_YEAR 0x8 /* 8 4 2 1 | 8 4 2 1 */
-#define RTC8564_REG_AL_MIN 0x9 /* AE 4 2 1 | 8 4 2 1 */
-#define RTC8564_REG_AL_HR 0xa /* AE 4 2 1 | 8 4 2 1 */
-#define RTC8564_REG_AL_DAY 0xb /* AE x 2 1 | 8 4 2 1 */
-#define RTC8564_REG_AL_WDAY 0xc /* AE x x x | x 4 2 1 */
-#define RTC8564_REG_CLKOUT 0xd /* FE x x x | x x FD1 FD0 */
-#define RTC8564_REG_TCTL 0xe /* TE x x x | x x FD1 FD0 */
-#define RTC8564_REG_TIMER 0xf /* 8 bit binary */
-
-/* Control reg */
-#define RTC8564_CTRL1_TEST1 (1<<3)
-#define RTC8564_CTRL1_STOP (1<<5)
-#define RTC8564_CTRL1_TEST2 (1<<7)
-
-#define RTC8564_CTRL2_TIE (1<<0)
-#define RTC8564_CTRL2_AIE (1<<1)
-#define RTC8564_CTRL2_TF (1<<2)
-#define RTC8564_CTRL2_AF (1<<3)
-#define RTC8564_CTRL2_TI_TP (1<<4)
-
-/* CLKOUT frequencies */
-#define RTC8564_FD_32768HZ (0x0)
-#define RTC8564_FD_1024HZ (0x1)
-#define RTC8564_FD_32 (0x2)
-#define RTC8564_FD_1HZ (0x3)
-
-/* Timer CTRL */
-#define RTC8564_TD_4096HZ (0x0)
-#define RTC8564_TD_64HZ (0x1)
-#define RTC8564_TD_1HZ (0x2)
-#define RTC8564_TD_1_60HZ (0x3)
-
-#define I2C_DRIVERID_RTC8564 0xf000
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
index 1af3dfbb8086..179b1e022d80 100644
--- a/drivers/i2c/chips/tps65010.c
+++ b/drivers/i2c/chips/tps65010.c
@@ -32,6 +32,7 @@
#include <linux/suspend.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
+#include <linux/mutex.h>
#include <asm/irq.h>
#include <asm/mach-types.h>
@@ -81,7 +82,7 @@ enum tps_model {
struct tps65010 {
struct i2c_client client;
- struct semaphore lock;
+ struct mutex lock;
int irq;
struct work_struct work;
struct dentry *file;
@@ -218,7 +219,7 @@ static int dbg_show(struct seq_file *s, void *_)
seq_printf(s, "driver %s\nversion %s\nchip %s\n\n",
DRIVER_NAME, DRIVER_VERSION, chip);
- down(&tps->lock);
+ mutex_lock(&tps->lock);
/* FIXME how can we tell whether a battery is present?
* likely involves a charge gauging chip (like BQ26501).
@@ -300,7 +301,7 @@ static int dbg_show(struct seq_file *s, void *_)
(v2 & (1 << (4 + i))) ? "rising" : "falling");
}
- up(&tps->lock);
+ mutex_unlock(&tps->lock);
return 0;
}
@@ -416,7 +417,7 @@ static void tps65010_work(void *_tps)
{
struct tps65010 *tps = _tps;
- down(&tps->lock);
+ mutex_lock(&tps->lock);
tps65010_interrupt(tps);
@@ -444,7 +445,7 @@ static void tps65010_work(void *_tps)
if (test_and_clear_bit(FLAG_IRQ_ENABLE, &tps->flags))
enable_irq(tps->irq);
- up(&tps->lock);
+ mutex_unlock(&tps->lock);
}
static irqreturn_t tps65010_irq(int irq, void *_tps, struct pt_regs *regs)
@@ -505,7 +506,7 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind)
if (!tps)
return 0;
- init_MUTEX(&tps->lock);
+ mutex_init(&tps->lock);
INIT_WORK(&tps->work, tps65010_work, tps);
tps->irq = -1;
tps->client.addr = address;
@@ -695,7 +696,7 @@ int tps65010_set_gpio_out_value(unsigned gpio, unsigned value)
if ((gpio < GPIO1) || (gpio > GPIO4))
return -EINVAL;
- down(&the_tps->lock);
+ mutex_lock(&the_tps->lock);
defgpio = i2c_smbus_read_byte_data(&the_tps->client, TPS_DEFGPIO);
@@ -720,7 +721,7 @@ int tps65010_set_gpio_out_value(unsigned gpio, unsigned value)
gpio, value ? "high" : "low",
i2c_smbus_read_byte_data(&the_tps->client, TPS_DEFGPIO));
- up(&the_tps->lock);
+ mutex_unlock(&the_tps->lock);
return status;
}
EXPORT_SYMBOL(tps65010_set_gpio_out_value);
@@ -745,7 +746,7 @@ int tps65010_set_led(unsigned led, unsigned mode)
led = LED2;
}
- down(&the_tps->lock);
+ mutex_lock(&the_tps->lock);
pr_debug("%s: led%i_on 0x%02x\n", DRIVER_NAME, led,
i2c_smbus_read_byte_data(&the_tps->client,
@@ -771,7 +772,7 @@ int tps65010_set_led(unsigned led, unsigned mode)
default:
printk(KERN_ERR "%s: Wrong mode parameter for set_led()\n",
DRIVER_NAME);
- up(&the_tps->lock);
+ mutex_unlock(&the_tps->lock);
return -EINVAL;
}
@@ -781,7 +782,7 @@ int tps65010_set_led(unsigned led, unsigned mode)
if (status != 0) {
printk(KERN_ERR "%s: Failed to write led%i_on register\n",
DRIVER_NAME, led);
- up(&the_tps->lock);
+ mutex_unlock(&the_tps->lock);
return status;
}
@@ -794,7 +795,7 @@ int tps65010_set_led(unsigned led, unsigned mode)
if (status != 0) {
printk(KERN_ERR "%s: Failed to write led%i_per register\n",
DRIVER_NAME, led);
- up(&the_tps->lock);
+ mutex_unlock(&the_tps->lock);
return status;
}
@@ -802,7 +803,7 @@ int tps65010_set_led(unsigned led, unsigned mode)
i2c_smbus_read_byte_data(&the_tps->client,
TPS_LED1_PER + offs));
- up(&the_tps->lock);
+ mutex_unlock(&the_tps->lock);
return status;
}
@@ -820,7 +821,7 @@ int tps65010_set_vib(unsigned value)
if (!the_tps)
return -ENODEV;
- down(&the_tps->lock);
+ mutex_lock(&the_tps->lock);
vdcdc2 = i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC2);
vdcdc2 &= ~(1 << 1);
@@ -831,7 +832,7 @@ int tps65010_set_vib(unsigned value)
pr_debug("%s: vibrator %s\n", DRIVER_NAME, value ? "on" : "off");
- up(&the_tps->lock);
+ mutex_unlock(&the_tps->lock);
return status;
}
EXPORT_SYMBOL(tps65010_set_vib);
@@ -848,7 +849,7 @@ int tps65010_set_low_pwr(unsigned mode)
if (!the_tps)
return -ENODEV;
- down(&the_tps->lock);
+ mutex_lock(&the_tps->lock);
pr_debug("%s: %s low_pwr, vdcdc1 0x%02x\n", DRIVER_NAME,
mode ? "enable" : "disable",
@@ -876,7 +877,7 @@ int tps65010_set_low_pwr(unsigned mode)
pr_debug("%s: vdcdc1 0x%02x\n", DRIVER_NAME,
i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1));
- up(&the_tps->lock);
+ mutex_unlock(&the_tps->lock);
return status;
}
@@ -894,7 +895,7 @@ int tps65010_config_vregs1(unsigned value)
if (!the_tps)
return -ENODEV;
- down(&the_tps->lock);
+ mutex_lock(&the_tps->lock);
pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME,
i2c_smbus_read_byte_data(&the_tps->client, TPS_VREGS1));
@@ -909,7 +910,7 @@ int tps65010_config_vregs1(unsigned value)
pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME,
i2c_smbus_read_byte_data(&the_tps->client, TPS_VREGS1));
- up(&the_tps->lock);
+ mutex_unlock(&the_tps->lock);
return status;
}
@@ -931,7 +932,7 @@ int tps65013_set_low_pwr(unsigned mode)
if (!the_tps || the_tps->por)
return -ENODEV;
- down(&the_tps->lock);
+ mutex_lock(&the_tps->lock);
pr_debug("%s: %s low_pwr, chgconfig 0x%02x vdcdc1 0x%02x\n",
DRIVER_NAME,
@@ -959,7 +960,7 @@ int tps65013_set_low_pwr(unsigned mode)
if (status != 0) {
printk(KERN_ERR "%s: Failed to write chconfig register\n",
DRIVER_NAME);
- up(&the_tps->lock);
+ mutex_unlock(&the_tps->lock);
return status;
}
@@ -977,7 +978,7 @@ int tps65013_set_low_pwr(unsigned mode)
pr_debug("%s: vdcdc1 0x%02x\n", DRIVER_NAME,
i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1));
- up(&the_tps->lock);
+ mutex_unlock(&the_tps->lock);
return status;
}
diff --git a/drivers/i2c/chips/x1205.c b/drivers/i2c/chips/x1205.c
deleted file mode 100644
index 245fffa92dbd..000000000000
--- a/drivers/i2c/chips/x1205.c
+++ /dev/null
@@ -1,698 +0,0 @@
-/*
- * x1205.c - An i2c driver for the Xicor X1205 RTC
- * Copyright 2004 Karen Spearel
- * Copyright 2005 Alessandro Zummo
- *
- * please send all reports to:
- * kas11 at tampabay dot rr dot com
- * a dot zummo at towertech dot it
- *
- * based on the other drivers in this same directory.
- *
- * 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.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/string.h>
-#include <linux/bcd.h>
-#include <linux/rtc.h>
-#include <linux/list.h>
-
-#include <linux/x1205.h>
-
-#define DRV_VERSION "0.9.9"
-
-/* Addresses to scan: none. This chip is located at
- * 0x6f and uses a two bytes register addressing.
- * Two bytes need to be written to read a single register,
- * while most other chips just require one and take the second
- * one as the data to be written. To prevent corrupting
- * unknown chips, the user must explicitely set the probe parameter.
- */
-
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
-
-/* Insmod parameters */
-I2C_CLIENT_INSMOD;
-I2C_CLIENT_MODULE_PARM(hctosys,
- "Set the system time from the hardware clock upon initialization");
-
-/* offsets into CCR area */
-
-#define CCR_SEC 0
-#define CCR_MIN 1
-#define CCR_HOUR 2
-#define CCR_MDAY 3
-#define CCR_MONTH 4
-#define CCR_YEAR 5
-#define CCR_WDAY 6
-#define CCR_Y2K 7
-
-#define X1205_REG_SR 0x3F /* status register */
-#define X1205_REG_Y2K 0x37
-#define X1205_REG_DW 0x36
-#define X1205_REG_YR 0x35
-#define X1205_REG_MO 0x34
-#define X1205_REG_DT 0x33
-#define X1205_REG_HR 0x32
-#define X1205_REG_MN 0x31
-#define X1205_REG_SC 0x30
-#define X1205_REG_DTR 0x13
-#define X1205_REG_ATR 0x12
-#define X1205_REG_INT 0x11
-#define X1205_REG_0 0x10
-#define X1205_REG_Y2K1 0x0F
-#define X1205_REG_DWA1 0x0E
-#define X1205_REG_YRA1 0x0D
-#define X1205_REG_MOA1 0x0C
-#define X1205_REG_DTA1 0x0B
-#define X1205_REG_HRA1 0x0A
-#define X1205_REG_MNA1 0x09
-#define X1205_REG_SCA1 0x08
-#define X1205_REG_Y2K0 0x07
-#define X1205_REG_DWA0 0x06
-#define X1205_REG_YRA0 0x05
-#define X1205_REG_MOA0 0x04
-#define X1205_REG_DTA0 0x03
-#define X1205_REG_HRA0 0x02
-#define X1205_REG_MNA0 0x01
-#define X1205_REG_SCA0 0x00
-
-#define X1205_CCR_BASE 0x30 /* Base address of CCR */
-#define X1205_ALM0_BASE 0x00 /* Base address of ALARM0 */
-
-#define X1205_SR_RTCF 0x01 /* Clock failure */
-#define X1205_SR_WEL 0x02 /* Write Enable Latch */
-#define X1205_SR_RWEL 0x04 /* Register Write Enable */
-
-#define X1205_DTR_DTR0 0x01
-#define X1205_DTR_DTR1 0x02
-#define X1205_DTR_DTR2 0x04
-
-#define X1205_HR_MIL 0x80 /* Set in ccr.hour for 24 hr mode */
-
-/* Prototypes */
-static int x1205_attach(struct i2c_adapter *adapter);
-static int x1205_detach(struct i2c_client *client);
-static int x1205_probe(struct i2c_adapter *adapter, int address, int kind);
-static int x1205_command(struct i2c_client *client, unsigned int cmd,
- void *arg);
-
-static struct i2c_driver x1205_driver = {
- .driver = {
- .name = "x1205",
- },
- .attach_adapter = &x1205_attach,
- .detach_client = &x1205_detach,
-};
-
-struct x1205_data {
- struct i2c_client client;
- struct list_head list;
- unsigned int epoch;
-};
-
-static const unsigned char days_in_mo[] =
- { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-
-static LIST_HEAD(x1205_clients);
-
-/* Workaround until the I2C subsytem will allow to send
- * commands to a specific client. This function will send the command
- * to the first client.
- */
-int x1205_do_command(unsigned int cmd, void *arg)
-{
- struct list_head *walk;
- struct list_head *tmp;
- struct x1205_data *data;
-
- list_for_each_safe(walk, tmp, &x1205_clients) {
- data = list_entry(walk, struct x1205_data, list);
- return x1205_command(&data->client, cmd, arg);
- }
-
- return -ENODEV;
-}
-
-#define is_leap(year) \
- ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
-
-/* make sure the rtc_time values are in bounds */
-static int x1205_validate_tm(struct rtc_time *tm)
-{
- int year = tm->tm_year + 1900;
-
- if ((tm->tm_year < 70) || (tm->tm_year > 255))
- return -EINVAL;
-
- if ((tm->tm_mon > 11) || (tm->tm_mday == 0))
- return -EINVAL;
-
- if (tm->tm_mday > days_in_mo[tm->tm_mon]
- + ((tm->tm_mon == 1) && is_leap(year)))
- return -EINVAL;
-
- if ((tm->tm_hour >= 24) || (tm->tm_min >= 60) || (tm->tm_sec >= 60))
- return -EINVAL;
-
- return 0;
-}
-
-/*
- * In the routines that deal directly with the x1205 hardware, we use
- * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch
- * Epoch is initialized as 2000. Time is set to UTC.
- */
-static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
- u8 reg_base)
-{
- unsigned char dt_addr[2] = { 0, reg_base };
- static unsigned char sr_addr[2] = { 0, X1205_REG_SR };
-
- unsigned char buf[8], sr;
-
- struct i2c_msg msgs[] = {
- { client->addr, 0, 2, sr_addr }, /* setup read ptr */
- { client->addr, I2C_M_RD, 1, &sr }, /* read status */
- { client->addr, 0, 2, dt_addr }, /* setup read ptr */
- { client->addr, I2C_M_RD, 8, buf }, /* read date */
- };
-
- struct x1205_data *data = i2c_get_clientdata(client);
-
- /* read status register */
- if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
- dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
- return -EIO;
- }
-
- /* check for battery failure */
- if (sr & X1205_SR_RTCF) {
- dev_warn(&client->dev,
- "Clock had a power failure, you must set the date.\n");
- return -EINVAL;
- }
-
- /* read date registers */
- if ((i2c_transfer(client->adapter, &msgs[2], 2)) != 2) {
- dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
- return -EIO;
- }
-
- dev_dbg(&client->dev,
- "%s: raw read data - sec=%02x, min=%02x, hr=%02x, "
- "mday=%02x, mon=%02x, year=%02x, wday=%02x, y2k=%02x\n",
- __FUNCTION__,
- buf[0], buf[1], buf[2], buf[3],
- buf[4], buf[5], buf[6], buf[7]);
-
- tm->tm_sec = BCD2BIN(buf[CCR_SEC]);
- tm->tm_min = BCD2BIN(buf[CCR_MIN]);
- tm->tm_hour = BCD2BIN(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */
- tm->tm_mday = BCD2BIN(buf[CCR_MDAY]);
- tm->tm_mon = BCD2BIN(buf[CCR_MONTH]);
- data->epoch = BCD2BIN(buf[CCR_Y2K]) * 100;
- tm->tm_year = BCD2BIN(buf[CCR_YEAR]) + data->epoch - 1900;
- tm->tm_wday = buf[CCR_WDAY];
-
- dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
- "mday=%d, mon=%d, year=%d, wday=%d\n",
- __FUNCTION__,
- tm->tm_sec, tm->tm_min, tm->tm_hour,
- tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
-
- return 0;
-}
-
-static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
- int datetoo, u8 reg_base)
-{
- int i, err, xfer;
-
- unsigned char buf[8];
-
- static const unsigned char wel[3] = { 0, X1205_REG_SR,
- X1205_SR_WEL };
-
- static const unsigned char rwel[3] = { 0, X1205_REG_SR,
- X1205_SR_WEL | X1205_SR_RWEL };
-
- static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 };
-
- struct x1205_data *data = i2c_get_clientdata(client);
-
- /* check if all values in the tm struct are correct */
- if ((err = x1205_validate_tm(tm)) < 0)
- return err;
-
- dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
- "mday=%d, mon=%d, year=%d, wday=%d\n",
- __FUNCTION__,
- tm->tm_sec, tm->tm_min, tm->tm_hour,
- tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
-
- buf[CCR_SEC] = BIN2BCD(tm->tm_sec);
- buf[CCR_MIN] = BIN2BCD(tm->tm_min);
-
- /* set hour and 24hr bit */
- buf[CCR_HOUR] = BIN2BCD(tm->tm_hour) | X1205_HR_MIL;
-
- /* should we also set the date? */
- if (datetoo) {
- buf[CCR_MDAY] = BIN2BCD(tm->tm_mday);
-
- /* month, 0 - 11 */
- buf[CCR_MONTH] = BIN2BCD(tm->tm_mon);
-
- /* year, since 1900 */
- buf[CCR_YEAR] = BIN2BCD(tm->tm_year + 1900 - data->epoch);
- buf[CCR_WDAY] = tm->tm_wday & 0x07;
- buf[CCR_Y2K] = BIN2BCD(data->epoch / 100);
- }
-
- /* this sequence is required to unlock the chip */
- xfer = i2c_master_send(client, wel, 3);
- if (xfer != 3) {
- dev_err(&client->dev, "%s: wel - %d\n", __FUNCTION__, xfer);
- return -EIO;
- }
-
- xfer = i2c_master_send(client, rwel, 3);
- if (xfer != 3) {
- dev_err(&client->dev, "%s: rwel - %d\n", __FUNCTION__, xfer);
- return -EIO;
- }
-
- /* write register's data */
- for (i = 0; i < (datetoo ? 8 : 3); i++) {
- unsigned char rdata[3] = { 0, reg_base + i, buf[i] };
-
- xfer = i2c_master_send(client, rdata, 3);
- if (xfer != 3) {
- dev_err(&client->dev,
- "%s: xfer=%d addr=%02x, data=%02x\n",
- __FUNCTION__,
- xfer, rdata[1], rdata[2]);
- return -EIO;
- }
- };
-
- /* disable further writes */
- xfer = i2c_master_send(client, diswe, 3);
- if (xfer != 3) {
- dev_err(&client->dev, "%s: diswe - %d\n", __FUNCTION__, xfer);
- return -EIO;
- }
-
- return 0;
-}
-
-static int x1205_get_dtrim(struct i2c_client *client, int *trim)
-{
- unsigned char dtr;
- static unsigned char dtr_addr[2] = { 0, X1205_REG_DTR };
-
- struct i2c_msg msgs[] = {
- { client->addr, 0, 2, dtr_addr }, /* setup read ptr */
- { client->addr, I2C_M_RD, 1, &dtr }, /* read dtr */
- };
-
- /* read dtr register */
- if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
- dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
- return -EIO;
- }
-
- dev_dbg(&client->dev, "%s: raw dtr=%x\n", __FUNCTION__, dtr);
-
- *trim = 0;
-
- if (dtr & X1205_DTR_DTR0)
- *trim += 20;
-
- if (dtr & X1205_DTR_DTR1)
- *trim += 10;
-
- if (dtr & X1205_DTR_DTR2)
- *trim = -*trim;
-
- return 0;
-}
-
-static int x1205_get_atrim(struct i2c_client *client, int *trim)
-{
- s8 atr;
- static unsigned char atr_addr[2] = { 0, X1205_REG_ATR };
-
- struct i2c_msg msgs[] = {
- { client->addr, 0, 2, atr_addr }, /* setup read ptr */
- { client->addr, I2C_M_RD, 1, &atr }, /* read atr */
- };
-
- /* read atr register */
- if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
- dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
- return -EIO;
- }
-
- dev_dbg(&client->dev, "%s: raw atr=%x\n", __FUNCTION__, atr);
-
- /* atr is a two's complement value on 6 bits,
- * perform sign extension. The formula is
- * Catr = (atr * 0.25pF) + 11.00pF.
- */
- if (atr & 0x20)
- atr |= 0xC0;
-
- dev_dbg(&client->dev, "%s: raw atr=%x (%d)\n", __FUNCTION__, atr, atr);
-
- *trim = (atr * 250) + 11000;
-
- dev_dbg(&client->dev, "%s: real=%d\n", __FUNCTION__, *trim);
-
- return 0;
-}
-
-static int x1205_hctosys(struct i2c_client *client)
-{
- int err;
-
- struct rtc_time tm;
- struct timespec tv;
-
- err = x1205_command(client, X1205_CMD_GETDATETIME, &tm);
-
- if (err) {
- dev_err(&client->dev,
- "Unable to set the system clock\n");
- return err;
- }
-
- /* IMPORTANT: the RTC only stores whole seconds. It is arbitrary
- * whether it stores the most close value or the value with partial
- * seconds truncated. However, it is important that we use it to store
- * the truncated value. This is because otherwise it is necessary,
- * in an rtc sync function, to read both xtime.tv_sec and
- * xtime.tv_nsec. On some processors (i.e. ARM), an atomic read
- * of >32bits is not possible. So storing the most close value would
- * slow down the sync API. So here we have the truncated value and
- * the best guess is to add 0.5s.
- */
-
- tv.tv_nsec = NSEC_PER_SEC >> 1;
-
- /* WARNING: this is not the C library 'mktime' call, it is a built in
- * inline function from include/linux/time.h. It expects (requires)
- * the month to be in the range 1-12
- */
-
- tv.tv_sec = mktime(tm.tm_year + 1900, tm.tm_mon + 1,
- tm.tm_mday, tm.tm_hour,
- tm.tm_min, tm.tm_sec);
-
- do_settimeofday(&tv);
-
- dev_info(&client->dev,
- "setting the system clock to %d-%d-%d %d:%d:%d\n",
- tm.tm_year + 1900, tm.tm_mon + 1,
- tm.tm_mday, tm.tm_hour, tm.tm_min,
- tm.tm_sec);
-
- return 0;
-}
-
-struct x1205_limit
-{
- unsigned char reg;
- unsigned char mask;
- unsigned char min;
- unsigned char max;
-};
-
-static int x1205_validate_client(struct i2c_client *client)
-{
- int i, xfer;
-
- /* Probe array. We will read the register at the specified
- * address and check if the given bits are zero.
- */
- static const unsigned char probe_zero_pattern[] = {
- /* register, mask */
- X1205_REG_SR, 0x18,
- X1205_REG_DTR, 0xF8,
- X1205_REG_ATR, 0xC0,
- X1205_REG_INT, 0x18,
- X1205_REG_0, 0xFF,
- };
-
- static const struct x1205_limit probe_limits_pattern[] = {
- /* register, mask, min, max */
- { X1205_REG_Y2K, 0xFF, 19, 20 },
- { X1205_REG_DW, 0xFF, 0, 6 },
- { X1205_REG_YR, 0xFF, 0, 99 },
- { X1205_REG_MO, 0xFF, 0, 12 },
- { X1205_REG_DT, 0xFF, 0, 31 },
- { X1205_REG_HR, 0x7F, 0, 23 },
- { X1205_REG_MN, 0xFF, 0, 59 },
- { X1205_REG_SC, 0xFF, 0, 59 },
- { X1205_REG_Y2K1, 0xFF, 19, 20 },
- { X1205_REG_Y2K0, 0xFF, 19, 20 },
- };
-
- /* check that registers have bits a 0 where expected */
- for (i = 0; i < ARRAY_SIZE(probe_zero_pattern); i += 2) {
- unsigned char buf;
-
- unsigned char addr[2] = { 0, probe_zero_pattern[i] };
-
- struct i2c_msg msgs[2] = {
- { client->addr, 0, 2, addr },
- { client->addr, I2C_M_RD, 1, &buf },
- };
-
- xfer = i2c_transfer(client->adapter, msgs, 2);
- if (xfer != 2) {
- dev_err(&client->adapter->dev,
- "%s: could not read register %x\n",
- __FUNCTION__, addr[1]);
-
- return -EIO;
- }
-
- if ((buf & probe_zero_pattern[i+1]) != 0) {
- dev_err(&client->adapter->dev,
- "%s: register=%02x, zero pattern=%d, value=%x\n",
- __FUNCTION__, addr[1], i, buf);
-
- return -ENODEV;
- }
- }
-
- /* check limits (only registers with bcd values) */
- for (i = 0; i < ARRAY_SIZE(probe_limits_pattern); i++) {
- unsigned char reg, value;
-
- unsigned char addr[2] = { 0, probe_limits_pattern[i].reg };
-
- struct i2c_msg msgs[2] = {
- { client->addr, 0, 2, addr },
- { client->addr, I2C_M_RD, 1, &reg },
- };
-
- xfer = i2c_transfer(client->adapter, msgs, 2);
-
- if (xfer != 2) {
- dev_err(&client->adapter->dev,
- "%s: could not read register %x\n",
- __FUNCTION__, addr[1]);
-
- return -EIO;
- }
-
- value = BCD2BIN(reg & probe_limits_pattern[i].mask);
-
- if (value > probe_limits_pattern[i].max ||
- value < probe_limits_pattern[i].min) {
- dev_dbg(&client->adapter->dev,
- "%s: register=%x, lim pattern=%d, value=%d\n",
- __FUNCTION__, addr[1], i, value);
-
- return -ENODEV;
- }
- }
-
- return 0;
-}
-
-static int x1205_attach(struct i2c_adapter *adapter)
-{
- dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
-
- return i2c_probe(adapter, &addr_data, x1205_probe);
-}
-
-int x1205_direct_attach(int adapter_id,
- struct i2c_client_address_data *address_data)
-{
- int err;
- struct i2c_adapter *adapter = i2c_get_adapter(adapter_id);
-
- if (adapter) {
- err = i2c_probe(adapter,
- address_data, x1205_probe);
-
- i2c_put_adapter(adapter);
-
- return err;
- }
-
- return -ENODEV;
-}
-
-static int x1205_probe(struct i2c_adapter *adapter, int address, int kind)
-{
- struct i2c_client *client;
- struct x1205_data *data;
-
- int err = 0;
-
- dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
-
- if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
- err = -ENODEV;
- goto exit;
- }
-
- if (!(data = kzalloc(sizeof(struct x1205_data), GFP_KERNEL))) {
- err = -ENOMEM;
- goto exit;
- }
-
- /* Initialize our structures */
- data->epoch = 2000;
-
- client = &data->client;
- client->addr = address;
- client->driver = &x1205_driver;
- client->adapter = adapter;
-
- strlcpy(client->name, "x1205", I2C_NAME_SIZE);
-
- i2c_set_clientdata(client, data);
-
- /* Verify the chip is really an X1205 */
- if (kind < 0) {
- if (x1205_validate_client(client) < 0) {
- err = -ENODEV;
- goto exit_kfree;
- }
- }
-
- /* Inform the i2c layer */
- if ((err = i2c_attach_client(client)))
- goto exit_kfree;
-
- list_add(&data->list, &x1205_clients);
-
- dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
-
- /* If requested, set the system time */
- if (hctosys)
- x1205_hctosys(client);
-
- return 0;
-
-exit_kfree:
- kfree(data);
-
-exit:
- return err;
-}
-
-static int x1205_detach(struct i2c_client *client)
-{
- int err;
- struct x1205_data *data = i2c_get_clientdata(client);
-
- dev_dbg(&client->dev, "%s\n", __FUNCTION__);
-
- if ((err = i2c_detach_client(client)))
- return err;
-
- list_del(&data->list);
-
- kfree(data);
-
- return 0;
-}
-
-static int x1205_command(struct i2c_client *client, unsigned int cmd,
- void *param)
-{
- if (param == NULL)
- return -EINVAL;
-
- if (!capable(CAP_SYS_TIME))
- return -EACCES;
-
- dev_dbg(&client->dev, "%s: cmd=%d\n", __FUNCTION__, cmd);
-
- switch (cmd) {
- case X1205_CMD_GETDATETIME:
- return x1205_get_datetime(client, param, X1205_CCR_BASE);
-
- case X1205_CMD_SETTIME:
- return x1205_set_datetime(client, param, 0,
- X1205_CCR_BASE);
-
- case X1205_CMD_SETDATETIME:
- return x1205_set_datetime(client, param, 1,
- X1205_CCR_BASE);
-
- case X1205_CMD_GETALARM:
- return x1205_get_datetime(client, param, X1205_ALM0_BASE);
-
- case X1205_CMD_SETALARM:
- return x1205_set_datetime(client, param, 1,
- X1205_ALM0_BASE);
-
- case X1205_CMD_GETDTRIM:
- return x1205_get_dtrim(client, param);
-
- case X1205_CMD_GETATRIM:
- return x1205_get_atrim(client, param);
-
- default:
- return -EINVAL;
- }
-}
-
-static int __init x1205_init(void)
-{
- return i2c_add_driver(&x1205_driver);
-}
-
-static void __exit x1205_exit(void)
-{
- i2c_del_driver(&x1205_driver);
-}
-
-MODULE_AUTHOR(
- "Karen Spearel <kas11@tampabay.rr.com>, "
- "Alessandro Zummo <a.zummo@towertech.it>");
-MODULE_DESCRIPTION("Xicor X1205 RTC driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_VERSION);
-
-EXPORT_SYMBOL_GPL(x1205_do_command);
-EXPORT_SYMBOL_GPL(x1205_direct_attach);
-
-module_init(x1205_init);
-module_exit(x1205_exit);
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 1a2c9ab5d9e3..45e2cdf54736 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -31,12 +31,13 @@
#include <linux/idr.h>
#include <linux/seq_file.h>
#include <linux/platform_device.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
static LIST_HEAD(adapters);
static LIST_HEAD(drivers);
-static DECLARE_MUTEX(core_lists);
+static DEFINE_MUTEX(core_lists);
static DEFINE_IDR(i2c_adapter_idr);
/* match always succeeds, as we want the probe() to tell if we really accept this match */
@@ -153,7 +154,7 @@ int i2c_add_adapter(struct i2c_adapter *adap)
struct list_head *item;
struct i2c_driver *driver;
- down(&core_lists);
+ mutex_lock(&core_lists);
if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) {
res = -ENOMEM;
@@ -168,8 +169,8 @@ int i2c_add_adapter(struct i2c_adapter *adap)
}
adap->nr = id & MAX_ID_MASK;
- init_MUTEX(&adap->bus_lock);
- init_MUTEX(&adap->clist_lock);
+ mutex_init(&adap->bus_lock);
+ mutex_init(&adap->clist_lock);
list_add_tail(&adap->list,&adapters);
INIT_LIST_HEAD(&adap->clients);
@@ -203,7 +204,7 @@ int i2c_add_adapter(struct i2c_adapter *adap)
}
out_unlock:
- up(&core_lists);
+ mutex_unlock(&core_lists);
return res;
}
@@ -216,7 +217,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
struct i2c_client *client;
int res = 0;
- down(&core_lists);
+ mutex_lock(&core_lists);
/* First make sure that this adapter was ever added */
list_for_each_entry(adap_from_list, &adapters, list) {
@@ -272,7 +273,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name);
out_unlock:
- up(&core_lists);
+ mutex_unlock(&core_lists);
return res;
}
@@ -287,9 +288,7 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
{
struct list_head *item;
struct i2c_adapter *adapter;
- int res = 0;
-
- down(&core_lists);
+ int res;
/* add the driver to the list of i2c drivers in the driver core */
driver->driver.owner = owner;
@@ -297,8 +296,10 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
res = driver_register(&driver->driver);
if (res)
- goto out_unlock;
+ return res;
+ mutex_lock(&core_lists);
+
list_add_tail(&driver->list,&drivers);
pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);
@@ -310,9 +311,8 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
}
}
- out_unlock:
- up(&core_lists);
- return res;
+ mutex_unlock(&core_lists);
+ return 0;
}
EXPORT_SYMBOL(i2c_register_driver);
@@ -324,7 +324,7 @@ int i2c_del_driver(struct i2c_driver *driver)
int res = 0;
- down(&core_lists);
+ mutex_lock(&core_lists);
/* Have a look at each adapter, if clients of this driver are still
* attached. If so, detach them to be able to kill the driver
@@ -363,7 +363,7 @@ int i2c_del_driver(struct i2c_driver *driver)
pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name);
out_unlock:
- up(&core_lists);
+ mutex_unlock(&core_lists);
return 0;
}
@@ -384,9 +384,9 @@ int i2c_check_addr(struct i2c_adapter *adapter, int addr)
{
int rval;
- down(&adapter->clist_lock);
+ mutex_lock(&adapter->clist_lock);
rval = __i2c_check_addr(adapter, addr);
- up(&adapter->clist_lock);
+ mutex_unlock(&adapter->clist_lock);
return rval;
}
@@ -395,13 +395,13 @@ int i2c_attach_client(struct i2c_client *client)
{
struct i2c_adapter *adapter = client->adapter;
- down(&adapter->clist_lock);
+ mutex_lock(&adapter->clist_lock);
if (__i2c_check_addr(client->adapter, client->addr)) {
- up(&adapter->clist_lock);
+ mutex_unlock(&adapter->clist_lock);
return -EBUSY;
}
list_add_tail(&client->list,&adapter->clients);
- up(&adapter->clist_lock);
+ mutex_unlock(&adapter->clist_lock);
if (adapter->client_register) {
if (adapter->client_register(client)) {
@@ -450,12 +450,12 @@ int i2c_detach_client(struct i2c_client *client)
}
}
- down(&adapter->clist_lock);
+ mutex_lock(&adapter->clist_lock);
list_del(&client->list);
init_completion(&client->released);
device_remove_file(&client->dev, &dev_attr_client_name);
device_unregister(&client->dev);
- up(&adapter->clist_lock);
+ mutex_unlock(&adapter->clist_lock);
wait_for_completion(&client->released);
out:
@@ -513,19 +513,19 @@ void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg)
struct list_head *item;
struct i2c_client *client;
- down(&adap->clist_lock);
+ mutex_lock(&adap->clist_lock);
list_for_each(item,&adap->clients) {
client = list_entry(item, struct i2c_client, list);
if (!try_module_get(client->driver->driver.owner))
continue;
if (NULL != client->driver->command) {
- up(&adap->clist_lock);
+ mutex_unlock(&adap->clist_lock);
client->driver->command(client,cmd,arg);
- down(&adap->clist_lock);
+ mutex_lock(&adap->clist_lock);
}
module_put(client->driver->driver.owner);
}
- up(&adap->clist_lock);
+ mutex_unlock(&adap->clist_lock);
}
static int __init i2c_init(void)
@@ -569,9 +569,9 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
}
#endif
- down(&adap->bus_lock);
+ mutex_lock(&adap->bus_lock);
ret = adap->algo->master_xfer(adap,msgs,num);
- up(&adap->bus_lock);
+ mutex_unlock(&adap->bus_lock);
return ret;
} else {
@@ -779,12 +779,12 @@ struct i2c_adapter* i2c_get_adapter(int id)
{
struct i2c_adapter *adapter;
- down(&core_lists);
+ mutex_lock(&core_lists);
adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id);
if (adapter && !try_module_get(adapter->owner))
adapter = NULL;
- up(&core_lists);
+ mutex_unlock(&core_lists);
return adapter;
}
@@ -919,12 +919,11 @@ s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command,
u8 length, u8 *values)
{
union i2c_smbus_data data;
- int i;
+
if (length > I2C_SMBUS_BLOCK_MAX)
length = I2C_SMBUS_BLOCK_MAX;
- for (i = 1; i <= length; i++)
- data.block[i] = values[i-1];
data.block[0] = length;
+ memcpy(&data.block[1], values, length);
return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
I2C_SMBUS_WRITE,command,
I2C_SMBUS_BLOCK_DATA,&data);
@@ -934,16 +933,14 @@ s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command,
s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *values)
{
union i2c_smbus_data data;
- int i;
+
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
I2C_SMBUS_READ,command,
I2C_SMBUS_I2C_BLOCK_DATA,&data))
return -1;
- else {
- for (i = 1; i <= data.block[0]; i++)
- values[i-1] = data.block[i];
- return data.block[0];
- }
+
+ memcpy(values, &data.block[1], data.block[0]);
+ return data.block[0];
}
s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command,
@@ -1118,10 +1115,10 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
flags &= I2C_M_TEN | I2C_CLIENT_PEC;
if (adapter->algo->smbus_xfer) {
- down(&adapter->bus_lock);
+ mutex_lock(&adapter->bus_lock);
res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write,
command,size,data);
- up(&adapter->bus_lock);
+ mutex_unlock(&adapter->bus_lock);
} else
res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write,
command,size,data);