summaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/busses')
-rw-r--r--drivers/i2c/busses/Kconfig33
-rw-r--r--drivers/i2c/busses/Makefile1
-rw-r--r--drivers/i2c/busses/i2c-amd756.c5
-rw-r--r--drivers/i2c/busses/i2c-au1550.c177
-rw-r--r--drivers/i2c/busses/i2c-au1550.h32
-rw-r--r--drivers/i2c/busses/i2c-bfin-twi.c3
-rw-r--r--drivers/i2c/busses/i2c-davinci.c1
-rw-r--r--drivers/i2c/busses/i2c-i801.c163
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.c191
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.h8
-rw-r--r--drivers/i2c/busses/i2c-iop3xx.c1
-rw-r--r--drivers/i2c/busses/i2c-ixp4xx.c178
-rw-r--r--drivers/i2c/busses/i2c-mpc.c29
-rw-r--r--drivers/i2c/busses/i2c-nforce2.c1
-rw-r--r--drivers/i2c/busses/i2c-omap.c2
-rw-r--r--drivers/i2c/busses/i2c-pasemi.c3
-rw-r--r--drivers/i2c/busses/i2c-piix4.c41
-rw-r--r--drivers/i2c/busses/i2c-pxa.c189
-rw-r--r--drivers/i2c/busses/i2c-sibyte.c29
-rw-r--r--drivers/i2c/busses/i2c-stub.c15
-rw-r--r--drivers/i2c/busses/i2c-viapro.c11
21 files changed, 538 insertions, 575 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index c466c6cfc2e5..8d12b26bb6c6 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -182,7 +182,8 @@ config I2C_I801
will be called i2c-i801.
config I2C_I810
- tristate "Intel 810/815"
+ tristate "Intel 810/815 (DEPRECATED)"
+ default n
depends on PCI
select I2C_ALGOBIT
help
@@ -195,6 +196,8 @@ config I2C_I810
i815
i845G
+ This driver is deprecated in favor of the i810fb and intelfb drivers.
+
This driver can also be built as a module. If so, the module
will be called i2c-i810.
@@ -259,20 +262,6 @@ config I2C_IOP3XX
This driver can also be built as a module. If so, the module
will be called i2c-iop3xx.
-config I2C_IXP4XX
- tristate "IXP4xx GPIO-Based I2C Interface (DEPRECATED)"
- depends on ARCH_IXP4XX
- select I2C_ALGOBIT
- help
- Say Y here if you have an Intel IXP4xx(420,421,422,425) based
- system and are using GPIO lines for an I2C bus.
-
- This support is also available as a module. If so, the module
- will be called i2c-ixp4xx.
-
- This driver is deprecated and will be dropped soon. Use i2c-gpio
- instead.
-
config I2C_IXP2000
tristate "IXP2000 GPIO-Based I2C Interface (DEPRECATED)"
depends on ARCH_IXP2000
@@ -396,7 +385,8 @@ config I2C_PASEMI
Supports the PA Semi PWRficient on-chip SMBus interfaces.
config I2C_PROSAVAGE
- tristate "S3/VIA (Pro)Savage"
+ tristate "S3/VIA (Pro)Savage (DEPRECATED)"
+ default n
depends on PCI
select I2C_ALGOBIT
help
@@ -407,6 +397,8 @@ config I2C_PROSAVAGE
S3/VIA KM266/VT8375 aka ProSavage8
S3/VIA KM133/VT8365 aka Savage4
+ This driver is deprecated in favor of the savagefb driver.
+
This support is also available as a module. If so, the module
will be called i2c-prosavage.
@@ -418,13 +410,16 @@ config I2C_S3C2410
Samsung S3C2410 based System-on-Chip devices.
config I2C_SAVAGE4
- tristate "S3 Savage 4"
- depends on PCI && EXPERIMENTAL
+ tristate "S3 Savage 4 (DEPRECATED)"
+ default n
+ depends on PCI
select I2C_ALGOBIT
help
If you say yes to this option, support will be included for the
S3 Savage 4 I2C interface.
+ This driver is deprecated in favor of the savagefb driver.
+
This driver can also be built as a module. If so, the module
will be called i2c-savage4.
@@ -611,7 +606,7 @@ config I2C_VIAPRO
VT8231
VT8233/A
VT8235
- VT8237R/A
+ VT8237R/A/S
VT8251
CX700
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 81d43c27cf93..ea7068f1eb6b 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -20,7 +20,6 @@ obj-$(CONFIG_I2C_I810) += i2c-i810.o
obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o
obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o
obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o
-obj-$(CONFIG_I2C_IXP4XX) += i2c-ixp4xx.o
obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o
obj-$(CONFIG_I2C_MPC) += i2c-mpc.o
obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
index 7490dc1771ae..573abe440842 100644
--- a/drivers/i2c/busses/i2c-amd756.c
+++ b/drivers/i2c/busses/i2c-amd756.c
@@ -334,6 +334,10 @@ static int __devinit amd756_probe(struct pci_dev *pdev,
int error;
u8 temp;
+ /* driver_data might come from user-space, so check it */
+ if (id->driver_data > ARRAY_SIZE(chipname))
+ return -EINVAL;
+
if (amd756_ioport) {
dev_err(&pdev->dev, "Only one device supported "
"(you have a strange motherboard, btw)\n");
@@ -405,6 +409,7 @@ static struct pci_driver amd756_driver = {
.id_table = amd756_ids,
.probe = amd756_probe,
.remove = __devexit_p(amd756_remove),
+ .dynids.use_driver_data = 1,
};
static int __init amd756_init(void)
diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c
index 2f684166c43d..1953b26da56a 100644
--- a/drivers/i2c/busses/i2c-au1550.c
+++ b/drivers/i2c/busses/i2c-au1550.c
@@ -30,14 +30,22 @@
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/i2c.h>
+#include <linux/slab.h>
#include <asm/mach-au1x00/au1xxx.h>
#include <asm/mach-au1x00/au1xxx_psc.h>
-#include "i2c-au1550.h"
+struct i2c_au1550_data {
+ u32 psc_base;
+ int xfer_timeout;
+ int ack_timeout;
+ struct i2c_adapter adap;
+ struct resource *ioarea;
+};
static int
wait_xfer_done(struct i2c_au1550_data *adap)
@@ -105,7 +113,7 @@ wait_master_done(struct i2c_au1550_data *adap)
}
static int
-do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd)
+do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd, int q)
{
volatile psc_smb_t *sp;
u32 stat;
@@ -134,6 +142,10 @@ do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd)
if (rd)
addr |= 1;
+ /* zero-byte xfers stop immediately */
+ if (q)
+ addr |= PSC_SMBTXRX_STP;
+
/* Put byte into fifo, start up master.
*/
sp->psc_smbtxrx = addr;
@@ -142,7 +154,7 @@ do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd)
au_sync();
if (wait_ack(adap))
return -EIO;
- return 0;
+ return (q) ? wait_master_done(adap) : 0;
}
static u32
@@ -262,7 +274,8 @@ au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
for (i = 0; !err && i < num; i++) {
p = &msgs[i];
- err = do_address(adap, p->addr, p->flags & I2C_M_RD);
+ err = do_address(adap, p->addr, p->flags & I2C_M_RD,
+ (p->len == 0));
if (err || !p->len)
continue;
if (p->flags & I2C_M_RD)
@@ -294,18 +307,48 @@ static const struct i2c_algorithm au1550_algo = {
* Prior to calling us, the 50MHz clock frequency and routing
* must have been set up for the PSC indicated by the adapter.
*/
-int
-i2c_au1550_add_bus(struct i2c_adapter *i2c_adap)
+static int __devinit
+i2c_au1550_probe(struct platform_device *pdev)
{
- struct i2c_au1550_data *adap = i2c_adap->algo_data;
- volatile psc_smb_t *sp;
- u32 stat;
+ struct i2c_au1550_data *priv;
+ volatile psc_smb_t *sp;
+ struct resource *r;
+ u32 stat;
+ int ret;
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!r) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ priv = kzalloc(sizeof(struct i2c_au1550_data), GFP_KERNEL);
+ if (!priv) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ priv->ioarea = request_mem_region(r->start, r->end - r->start + 1,
+ pdev->name);
+ if (!priv->ioarea) {
+ ret = -EBUSY;
+ goto out_mem;
+ }
- i2c_adap->algo = &au1550_algo;
+ priv->psc_base = r->start;
+ priv->xfer_timeout = 200;
+ priv->ack_timeout = 200;
+
+ priv->adap.id = I2C_HW_AU1550_PSC;
+ priv->adap.nr = pdev->id;
+ priv->adap.algo = &au1550_algo;
+ priv->adap.algo_data = priv;
+ priv->adap.dev.parent = &pdev->dev;
+ strlcpy(priv->adap.name, "Au1xxx PSC I2C", sizeof(priv->adap.name));
/* Now, set up the PSC for SMBus PIO mode.
*/
- sp = (volatile psc_smb_t *)(adap->psc_base);
+ sp = (volatile psc_smb_t *)priv->psc_base;
sp->psc_ctrl = PSC_CTRL_DISABLE;
au_sync();
sp->psc_sel = PSC_SEL_PS_SMBUSMODE;
@@ -343,87 +386,87 @@ i2c_au1550_add_bus(struct i2c_adapter *i2c_adap)
au_sync();
} while ((stat & PSC_SMBSTAT_DR) == 0);
- return i2c_add_adapter(i2c_adap);
-}
+ ret = i2c_add_numbered_adapter(&priv->adap);
+ if (ret == 0) {
+ platform_set_drvdata(pdev, priv);
+ return 0;
+ }
+ /* disable the PSC */
+ sp->psc_smbcfg = 0;
+ sp->psc_ctrl = PSC_CTRL_DISABLE;
+ au_sync();
-int
-i2c_au1550_del_bus(struct i2c_adapter *adap)
+ release_resource(priv->ioarea);
+ kfree(priv->ioarea);
+out_mem:
+ kfree(priv);
+out:
+ return ret;
+}
+
+static int __devexit
+i2c_au1550_remove(struct platform_device *pdev)
{
- return i2c_del_adapter(adap);
+ struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
+ volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
+
+ platform_set_drvdata(pdev, NULL);
+ i2c_del_adapter(&priv->adap);
+ sp->psc_smbcfg = 0;
+ sp->psc_ctrl = PSC_CTRL_DISABLE;
+ au_sync();
+ release_resource(priv->ioarea);
+ kfree(priv->ioarea);
+ kfree(priv);
+ return 0;
}
static int
-pb1550_reg(struct i2c_client *client)
+i2c_au1550_suspend(struct platform_device *pdev, pm_message_t state)
{
+ struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
+ volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
+
+ sp->psc_ctrl = PSC_CTRL_SUSPEND;
+ au_sync();
return 0;
}
static int
-pb1550_unreg(struct i2c_client *client)
+i2c_au1550_resume(struct platform_device *pdev)
{
+ struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
+ volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
+
+ sp->psc_ctrl = PSC_CTRL_ENABLE;
+ au_sync();
+ while (!(sp->psc_smbstat & PSC_SMBSTAT_SR))
+ au_sync();
return 0;
}
-static struct i2c_au1550_data pb1550_i2c_info = {
- SMBUS_PSC_BASE, 200, 200
-};
-
-static struct i2c_adapter pb1550_board_adapter = {
- name: "pb1550 adapter",
- id: I2C_HW_AU1550_PSC,
- algo: NULL,
- algo_data: &pb1550_i2c_info,
- client_register: pb1550_reg,
- client_unregister: pb1550_unreg,
+static struct platform_driver au1xpsc_smbus_driver = {
+ .driver = {
+ .name = "au1xpsc_smbus",
+ .owner = THIS_MODULE,
+ },
+ .probe = i2c_au1550_probe,
+ .remove = __devexit_p(i2c_au1550_remove),
+ .suspend = i2c_au1550_suspend,
+ .resume = i2c_au1550_resume,
};
-/* BIG hack to support the control interface on the Wolfson WM8731
- * audio codec on the Pb1550 board. We get an address and two data
- * bytes to write, create an i2c message, and send it across the
- * i2c transfer function. We do this here because we have access to
- * the i2c adapter structure.
- */
-static struct i2c_msg wm_i2c_msg; /* We don't want this stuff on the stack */
-static u8 i2cbuf[2];
-
-int
-pb1550_wm_codec_write(u8 addr, u8 reg, u8 val)
-{
- wm_i2c_msg.addr = addr;
- wm_i2c_msg.flags = 0;
- wm_i2c_msg.buf = i2cbuf;
- wm_i2c_msg.len = 2;
- i2cbuf[0] = reg;
- i2cbuf[1] = val;
-
- return pb1550_board_adapter.algo->master_xfer(&pb1550_board_adapter, &wm_i2c_msg, 1);
-}
-
static int __init
i2c_au1550_init(void)
{
- printk(KERN_INFO "Au1550 I2C: ");
-
- /* This is where we would set up a 50MHz clock source
- * and routing. On the Pb1550, the SMBus is PSC2, which
- * uses a shared clock with USB. This has been already
- * configured by Yamon as a 48MHz clock, close enough
- * for our work.
- */
- if (i2c_au1550_add_bus(&pb1550_board_adapter) < 0) {
- printk("failed to initialize.\n");
- return -ENODEV;
- }
-
- printk("initialized.\n");
- return 0;
+ return platform_driver_register(&au1xpsc_smbus_driver);
}
static void __exit
i2c_au1550_exit(void)
{
- i2c_au1550_del_bus(&pb1550_board_adapter);
+ platform_driver_unregister(&au1xpsc_smbus_driver);
}
MODULE_AUTHOR("Dan Malek, Embedded Edge, LLC.");
diff --git a/drivers/i2c/busses/i2c-au1550.h b/drivers/i2c/busses/i2c-au1550.h
deleted file mode 100644
index fce15d161ae7..000000000000
--- a/drivers/i2c/busses/i2c-au1550.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2004 Embedded Edge, LLC <dan@embeddededge.com>
- * 2.6 port by Matt Porter <mporter@kernel.crashing.org>
- *
- * 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.
- */
-
-#ifndef I2C_AU1550_H
-#define I2C_AU1550_H
-
-struct i2c_au1550_data {
- u32 psc_base;
- int xfer_timeout;
- int ack_timeout;
-};
-
-int i2c_au1550_add_bus(struct i2c_adapter *);
-int i2c_au1550_del_bus(struct i2c_adapter *);
-
-#endif /* I2C_AU1550_H */
diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c
index 67224a424aba..7dbdaeb707a9 100644
--- a/drivers/i2c/busses/i2c-bfin-twi.c
+++ b/drivers/i2c/busses/i2c-bfin-twi.c
@@ -550,6 +550,7 @@ static int i2c_bfin_twi_probe(struct platform_device *dev)
p_adap = &iface->adap;
p_adap->id = I2C_HW_BLACKFIN;
+ p_adap->nr = dev->id;
strlcpy(p_adap->name, dev->name, sizeof(p_adap->name));
p_adap->algo = &bfin_twi_algorithm;
p_adap->algo_data = iface;
@@ -576,7 +577,7 @@ static int i2c_bfin_twi_probe(struct platform_device *dev)
bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() | TWI_ENA);
SSYNC();
- rc = i2c_add_adapter(p_adap);
+ rc = i2c_add_numbered_adapter(p_adap);
if (rc < 0)
free_irq(iface->irq, iface);
else
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index 67679882ebef..cce5a614758d 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -510,7 +510,6 @@ static int davinci_i2c_probe(struct platform_device *pdev)
/* FIXME */
adap->timeout = 1;
- adap->retries = 1;
adap->nr = pdev->id;
r = i2c_add_numbered_adapter(adap);
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index ac27e5f84ebe..aa9157913b9a 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -4,6 +4,7 @@
Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>,
Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker
<mdsxyz123@yahoo.com>
+ Copyright (C) 2007 Jean Delvare <khali@linux-fr.org>
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
@@ -21,25 +22,34 @@
*/
/*
- SUPPORTED DEVICES PCI ID
- 82801AA 2413
- 82801AB 2423
- 82801BA 2443
- 82801CA/CAM 2483
- 82801DB 24C3 (HW PEC supported)
- 82801EB 24D3 (HW PEC supported)
- 6300ESB 25A4
- ICH6 266A
- ICH7 27DA
- ESB2 269B
- ICH8 283E
- ICH9 2930
- Tolapai 5032
- This driver supports several versions of Intel's I/O Controller Hubs (ICH).
- For SMBus support, they are similar to the PIIX4 and are part
- of Intel's '810' and other chipsets.
- See the file Documentation/i2c/busses/i2c-i801 for details.
- I2C Block Read and Process Call are not supported.
+ Supports the following Intel I/O Controller Hubs (ICH):
+
+ I/O Block I2C
+ region SMBus Block proc. block
+ Chip name PCI ID size PEC buffer call read
+ ----------------------------------------------------------------------
+ 82801AA (ICH) 0x2413 16 no no no no
+ 82801AB (ICH0) 0x2423 16 no no no no
+ 82801BA (ICH2) 0x2443 16 no no no no
+ 82801CA (ICH3) 0x2483 32 soft no no no
+ 82801DB (ICH4) 0x24c3 32 hard yes no no
+ 82801E (ICH5) 0x24d3 32 hard yes yes yes
+ 6300ESB 0x25a4 32 hard yes yes yes
+ 82801F (ICH6) 0x266a 32 hard yes yes yes
+ 6310ESB/6320ESB 0x269b 32 hard yes yes yes
+ 82801G (ICH7) 0x27da 32 hard yes yes yes
+ 82801H (ICH8) 0x283e 32 hard yes yes yes
+ 82801I (ICH9) 0x2930 32 hard yes yes yes
+ Tolapai 0x5032 32 hard yes ? ?
+
+ Features supported by this driver:
+ Software PEC no
+ Hardware PEC yes
+ Block buffer yes
+ Block process call transaction no
+ I2C block read transaction yes (doesn't use the block buffer)
+
+ See the file Documentation/i2c/busses/i2c-i801 for details.
*/
/* Note: we assume there can only be one I801, with one SMBus interface */
@@ -62,9 +72,9 @@
#define SMBHSTDAT0 (5 + i801_smba)
#define SMBHSTDAT1 (6 + i801_smba)
#define SMBBLKDAT (7 + i801_smba)
-#define SMBPEC (8 + i801_smba) /* ICH4 only */
-#define SMBAUXSTS (12 + i801_smba) /* ICH4 only */
-#define SMBAUXCTL (13 + i801_smba) /* ICH4 only */
+#define SMBPEC (8 + i801_smba) /* ICH3 and later */
+#define SMBAUXSTS (12 + i801_smba) /* ICH4 and later */
+#define SMBAUXCTL (13 + i801_smba) /* ICH4 and later */
/* PCI Address Constants */
#define SMBBAR 4
@@ -91,13 +101,13 @@
#define I801_BYTE 0x04
#define I801_BYTE_DATA 0x08
#define I801_WORD_DATA 0x0C
-#define I801_PROC_CALL 0x10 /* later chips only, unimplemented */
+#define I801_PROC_CALL 0x10 /* unimplemented */
#define I801_BLOCK_DATA 0x14
-#define I801_I2C_BLOCK_DATA 0x18 /* unimplemented */
+#define I801_I2C_BLOCK_DATA 0x18 /* ICH5 and later */
#define I801_BLOCK_LAST 0x34
-#define I801_I2C_BLOCK_LAST 0x38 /* unimplemented */
+#define I801_I2C_BLOCK_LAST 0x38 /* ICH5 and later */
#define I801_START 0x40
-#define I801_PEC_EN 0x80 /* ICH4 only */
+#define I801_PEC_EN 0x80 /* ICH3 and later */
/* I801 Hosts Status register bits */
#define SMBHSTSTS_BYTE_DONE 0x80
@@ -113,7 +123,12 @@ static unsigned long i801_smba;
static unsigned char i801_original_hstcfg;
static struct pci_driver i801_driver;
static struct pci_dev *I801_dev;
-static int isich4;
+
+#define FEATURE_SMBUS_PEC (1 << 0)
+#define FEATURE_BLOCK_BUFFER (1 << 1)
+#define FEATURE_BLOCK_PROC (1 << 2)
+#define FEATURE_I2C_BLOCK_READ (1 << 3)
+static unsigned int i801_features;
static int i801_transaction(int xact)
{
@@ -242,7 +257,8 @@ static int i801_block_transaction_by_block(union i2c_smbus_data *data,
}
static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
- char read_write, int hwpec)
+ char read_write, int command,
+ int hwpec)
{
int i, len;
int smbcmd;
@@ -259,16 +275,24 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
}
for (i = 1; i <= len; i++) {
- if (i == len && read_write == I2C_SMBUS_READ)
- smbcmd = I801_BLOCK_LAST;
- else
- smbcmd = I801_BLOCK_DATA;
+ if (i == len && read_write == I2C_SMBUS_READ) {
+ if (command == I2C_SMBUS_I2C_BLOCK_DATA)
+ smbcmd = I801_I2C_BLOCK_LAST;
+ else
+ smbcmd = I801_BLOCK_LAST;
+ } else {
+ if (command == I2C_SMBUS_I2C_BLOCK_DATA
+ && read_write == I2C_SMBUS_READ)
+ smbcmd = I801_I2C_BLOCK_DATA;
+ else
+ smbcmd = I801_BLOCK_DATA;
+ }
outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);
dev_dbg(&I801_dev->dev, "Block (pre %d): CNT=%02x, CMD=%02x, "
- "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
+ "ADD=%02x, DAT0=%02x, DAT1=%02x, BLKDAT=%02x\n", i,
inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
- inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
+ inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1), inb_p(SMBBLKDAT));
/* Make sure the SMBus host is ready to start transmitting */
temp = inb_p(SMBHSTSTS);
@@ -332,7 +356,8 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
dev_dbg(&I801_dev->dev, "Error: no response!\n");
}
- if (i == 1 && read_write == I2C_SMBUS_READ) {
+ if (i == 1 && read_write == I2C_SMBUS_READ
+ && command != I2C_SMBUS_I2C_BLOCK_DATA) {
len = inb_p(SMBHSTDAT0);
if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
return -1;
@@ -353,9 +378,9 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
temp);
}
dev_dbg(&I801_dev->dev, "Block (post %d): CNT=%02x, CMD=%02x, "
- "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
+ "ADD=%02x, DAT0=%02x, DAT1=%02x, BLKDAT=%02x\n", i,
inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
- inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
+ inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1), inb_p(SMBBLKDAT));
if (result < 0)
return result;
@@ -384,33 +409,38 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
pci_write_config_byte(I801_dev, SMBHSTCFG,
hostc | SMBHSTCFG_I2C_EN);
- } else {
+ } else if (!(i801_features & FEATURE_I2C_BLOCK_READ)) {
dev_err(&I801_dev->dev,
- "I2C_SMBUS_I2C_BLOCK_READ not DB!\n");
+ "I2C block read is unsupported!\n");
return -1;
}
}
- if (read_write == I2C_SMBUS_WRITE) {
+ if (read_write == I2C_SMBUS_WRITE
+ || command == I2C_SMBUS_I2C_BLOCK_DATA) {
if (data->block[0] < 1)
data->block[0] = 1;
if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
data->block[0] = I2C_SMBUS_BLOCK_MAX;
} else {
- data->block[0] = 32; /* max for reads */
+ data->block[0] = 32; /* max for SMBus block reads */
}
- if (isich4 && i801_set_block_buffer_mode() == 0 )
+ if ((i801_features & FEATURE_BLOCK_BUFFER)
+ && !(command == I2C_SMBUS_I2C_BLOCK_DATA
+ && read_write == I2C_SMBUS_READ)
+ && i801_set_block_buffer_mode() == 0)
result = i801_block_transaction_by_block(data, read_write,
hwpec);
else
result = i801_block_transaction_byte_by_byte(data, read_write,
- hwpec);
+ command, hwpec);
if (result == 0 && hwpec)
i801_wait_hwpec();
- if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
+ if (command == I2C_SMBUS_I2C_BLOCK_DATA
+ && read_write == I2C_SMBUS_WRITE) {
/* restore saved configuration register value */
pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
}
@@ -426,7 +456,7 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
int block = 0;
int ret, xact = 0;
- hwpec = isich4 && (flags & I2C_CLIENT_PEC)
+ hwpec = (i801_features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC)
&& size != I2C_SMBUS_QUICK
&& size != I2C_SMBUS_I2C_BLOCK_DATA;
@@ -462,12 +492,23 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
xact = I801_WORD_DATA;
break;
case I2C_SMBUS_BLOCK_DATA:
- case I2C_SMBUS_I2C_BLOCK_DATA:
outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
SMBHSTADD);
outb_p(command, SMBHSTCMD);
block = 1;
break;
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ /* NB: page 240 of ICH5 datasheet shows that the R/#W
+ * bit should be cleared here, even when reading */
+ outb_p((addr & 0x7f) << 1, SMBHSTADD);
+ if (read_write == I2C_SMBUS_READ) {
+ /* NB: page 240 of ICH5 datasheet also shows
+ * that DATA1 is the cmd field when reading */
+ outb_p(command, SMBHSTDAT1);
+ } else
+ outb_p(command, SMBHSTCMD);
+ block = 1;
+ break;
case I2C_SMBUS_PROC_CALL:
default:
dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size);
@@ -487,7 +528,7 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
/* Some BIOSes don't like it when PEC is enabled at reboot or resume
time, so we forcibly disable it after every transaction. Turn off
E32B for the same reason. */
- if (hwpec)
+ if (hwpec || block)
outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B),
SMBAUXCTL);
@@ -514,9 +555,11 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
static u32 i801_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
- I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
- I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
- | (isich4 ? I2C_FUNC_SMBUS_PEC : 0);
+ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+ I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK |
+ ((i801_features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0) |
+ ((i801_features & FEATURE_I2C_BLOCK_READ) ?
+ I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0);
}
static const struct i2c_algorithm smbus_algorithm = {
@@ -556,8 +599,8 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
int err;
I801_dev = dev;
+ i801_features = 0;
switch (dev->device) {
- case PCI_DEVICE_ID_INTEL_82801DB_3:
case PCI_DEVICE_ID_INTEL_82801EB_3:
case PCI_DEVICE_ID_INTEL_ESB_4:
case PCI_DEVICE_ID_INTEL_ICH6_16:
@@ -565,11 +608,13 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
case PCI_DEVICE_ID_INTEL_ESB2_17:
case PCI_DEVICE_ID_INTEL_ICH8_5:
case PCI_DEVICE_ID_INTEL_ICH9_6:
+ i801_features |= FEATURE_I2C_BLOCK_READ;
+ /* fall through */
+ case PCI_DEVICE_ID_INTEL_82801DB_3:
case PCI_DEVICE_ID_INTEL_TOLAPAI_1:
- isich4 = 1;
+ i801_features |= FEATURE_SMBUS_PEC;
+ i801_features |= FEATURE_BLOCK_BUFFER;
break;
- default:
- isich4 = 0;
}
err = pci_enable_device(dev);
@@ -610,6 +655,11 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
else
dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n");
+ /* Clear special mode bits */
+ if (i801_features & (FEATURE_SMBUS_PEC | FEATURE_BLOCK_BUFFER))
+ outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B),
+ SMBAUXCTL);
+
/* set up the sysfs linkage to our parent device */
i801_adapter.dev.parent = &dev->dev;
@@ -678,9 +728,8 @@ static void __exit i2c_i801_exit(void)
pci_unregister_driver(&i801_driver);
}
-MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl>, "
- "Philip Edelbrock <phil@netroedge.com>, "
- "and Mark D. Studebaker <mdsxyz123@yahoo.com>");
+MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>, "
+ "Jean Delvare <khali@linux-fr.org>");
MODULE_DESCRIPTION("I801 SMBus driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 9b43ff7270d0..7c7eb0cfeceb 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -6,7 +6,7 @@
* Copyright (c) 2003, 2004 Zultys Technologies.
* Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
*
- * Based on original work by
+ * Based on original work by
* Ian DaSilva <idasilva@mvista.com>
* Armin Kuster <akuster@mvista.com>
* Matt Porter <mporter@mvista.com>
@@ -86,8 +86,8 @@ static void dump_iic_regs(const char* header, struct ibm_iic_private* dev)
KERN_DEBUG " sts = 0x%02x, extsts = 0x%02x\n"
KERN_DEBUG " clkdiv = 0x%02x, xfrcnt = 0x%02x\n"
KERN_DEBUG " xtcntlss = 0x%02x, directcntl = 0x%02x\n",
- in_8(&iic->cntl), in_8(&iic->mdcntl), in_8(&iic->sts),
- in_8(&iic->extsts), in_8(&iic->clkdiv), in_8(&iic->xfrcnt),
+ in_8(&iic->cntl), in_8(&iic->mdcntl), in_8(&iic->sts),
+ in_8(&iic->extsts), in_8(&iic->clkdiv), in_8(&iic->xfrcnt),
in_8(&iic->xtcntlss), in_8(&iic->directcntl));
}
# define DUMP_REGS(h,dev) dump_iic_regs((h),(dev))
@@ -125,7 +125,7 @@ static inline void iic_interrupt_mode(struct ibm_iic_private* dev, int enable)
{
out_8(&dev->vaddr->intmsk, enable ? INTRMSK_EIMTC : 0);
}
-
+
/*
* Initialize IIC interface.
*/
@@ -134,7 +134,7 @@ static void iic_dev_init(struct ibm_iic_private* dev)
volatile struct iic_regs __iomem *iic = dev->vaddr;
DBG("%d: init\n", dev->idx);
-
+
/* Clear master address */
out_8(&iic->lmadr, 0);
out_8(&iic->hmadr, 0);
@@ -160,7 +160,7 @@ static void iic_dev_init(struct ibm_iic_private* dev)
/* Clear control register */
out_8(&iic->cntl, 0);
-
+
/* Enable interrupts if possible */
iic_interrupt_mode(dev, dev->irq >= 0);
@@ -171,7 +171,7 @@ static void iic_dev_init(struct ibm_iic_private* dev)
DUMP_REGS("iic_init", dev);
}
-/*
+/*
* Reset IIC interface
*/
static void iic_dev_reset(struct ibm_iic_private* dev)
@@ -179,42 +179,42 @@ static void iic_dev_reset(struct ibm_iic_private* dev)
volatile struct iic_regs __iomem *iic = dev->vaddr;
int i;
u8 dc;
-
+
DBG("%d: soft reset\n", dev->idx);
DUMP_REGS("reset", dev);
-
+
/* Place chip in the reset state */
out_8(&iic->xtcntlss, XTCNTLSS_SRST);
-
+
/* Check if bus is free */
- dc = in_8(&iic->directcntl);
+ dc = in_8(&iic->directcntl);
if (!DIRCTNL_FREE(dc)){
DBG("%d: trying to regain bus control\n", dev->idx);
-
+
/* Try to set bus free state */
- out_8(&iic->directcntl, DIRCNTL_SDAC | DIRCNTL_SCC);
-
+ out_8(&iic->directcntl, DIRCNTL_SDAC | DIRCNTL_SCC);
+
/* Wait until we regain bus control */
for (i = 0; i < 100; ++i){
dc = in_8(&iic->directcntl);
if (DIRCTNL_FREE(dc))
break;
-
+
/* Toggle SCL line */
dc ^= DIRCNTL_SCC;
out_8(&iic->directcntl, dc);
udelay(10);
dc ^= DIRCNTL_SCC;
out_8(&iic->directcntl, dc);
-
+
/* be nice */
cond_resched();
}
}
-
+
/* Remove reset */
out_8(&iic->xtcntlss, 0);
-
+
/* Reinitialize interface */
iic_dev_init(dev);
}
@@ -324,14 +324,14 @@ static irqreturn_t iic_handler(int irq, void *dev_id)
{
struct ibm_iic_private* dev = (struct ibm_iic_private*)dev_id;
volatile struct iic_regs __iomem *iic = dev->vaddr;
-
- DBG2("%d: irq handler, STS = 0x%02x, EXTSTS = 0x%02x\n",
+
+ DBG2("%d: irq handler, STS = 0x%02x, EXTSTS = 0x%02x\n",
dev->idx, in_8(&iic->sts), in_8(&iic->extsts));
-
+
/* Acknowledge IRQ and wakeup iic_wait_for_tc */
out_8(&iic->sts, STS_IRQA | STS_SCMP);
wake_up_interruptible(&dev->wq);
-
+
return IRQ_HANDLED;
}
@@ -341,19 +341,19 @@ static irqreturn_t iic_handler(int irq, void *dev_id)
*/
static int iic_xfer_result(struct ibm_iic_private* dev)
{
- volatile struct iic_regs __iomem *iic = dev->vaddr;
-
+ volatile struct iic_regs __iomem *iic = dev->vaddr;
+
if (unlikely(in_8(&iic->sts) & STS_ERR)){
- DBG("%d: xfer error, EXTSTS = 0x%02x\n", dev->idx,
+ DBG("%d: xfer error, EXTSTS = 0x%02x\n", dev->idx,
in_8(&iic->extsts));
-
+
/* Clear errors and possible pending IRQs */
- out_8(&iic->extsts, EXTSTS_IRQP | EXTSTS_IRQD |
+ out_8(&iic->extsts, EXTSTS_IRQP | EXTSTS_IRQD |
EXTSTS_LA | EXTSTS_ICT | EXTSTS_XFRA);
-
+
/* Flush master data buffer */
out_8(&iic->mdcntl, in_8(&iic->mdcntl) | MDCNTL_FMDB);
-
+
/* Is bus free?
* If error happened during combined xfer
* IIC interface is usually stuck in some strange
@@ -376,11 +376,11 @@ static void iic_abort_xfer(struct ibm_iic_private* dev)
{
volatile struct iic_regs __iomem *iic = dev->vaddr;
unsigned long x;
-
+
DBG("%d: iic_abort_xfer\n", dev->idx);
-
+
out_8(&iic->cntl, CNTL_HMT);
-
+
/*
* Wait for the abort command to complete.
* It's not worth to be optimized, just poll (timeout >= 1 tick)
@@ -405,13 +405,13 @@ static void iic_abort_xfer(struct ibm_iic_private* dev)
* Returns the number of transferred bytes or error (<0)
*/
static int iic_wait_for_tc(struct ibm_iic_private* dev){
-
+
volatile struct iic_regs __iomem *iic = dev->vaddr;
int ret = 0;
-
+
if (dev->irq >= 0){
/* Interrupt mode */
- ret = wait_event_interruptible_timeout(dev->wq,
+ ret = wait_event_interruptible_timeout(dev->wq,
!(in_8(&iic->sts) & STS_PT), dev->adap.timeout * HZ);
if (unlikely(ret < 0))
@@ -424,37 +424,37 @@ static int iic_wait_for_tc(struct ibm_iic_private* dev){
else {
/* Polling mode */
unsigned long x = jiffies + dev->adap.timeout * HZ;
-
+
while (in_8(&iic->sts) & STS_PT){
if (unlikely(time_after(jiffies, x))){
DBG("%d: poll timeout\n", dev->idx);
ret = -ETIMEDOUT;
break;
}
-
+
if (unlikely(signal_pending(current))){
DBG("%d: poll interrupted\n", dev->idx);
ret = -ERESTARTSYS;
break;
}
schedule();
- }
+ }
}
-
+
if (unlikely(ret < 0))
iic_abort_xfer(dev);
else
ret = iic_xfer_result(dev);
-
+
DBG2("%d: iic_wait_for_tc -> %d\n", dev->idx, ret);
-
+
return ret;
}
/*
* Low level master transfer routine
*/
-static int iic_xfer_bytes(struct ibm_iic_private* dev, struct i2c_msg* pm,
+static int iic_xfer_bytes(struct ibm_iic_private* dev, struct i2c_msg* pm,
int combined_xfer)
{
volatile struct iic_regs __iomem *iic = dev->vaddr;
@@ -465,48 +465,48 @@ static int iic_xfer_bytes(struct ibm_iic_private* dev, struct i2c_msg* pm,
u8 cntl = (in_8(&iic->cntl) & CNTL_AMD) | CNTL_PT;
if (pm->flags & I2C_M_RD)
cntl |= CNTL_RW;
-
+
loops = (len + 3) / 4;
for (i = 0; i < loops; ++i, len -= 4){
int count = len > 4 ? 4 : len;
u8 cmd = cntl | ((count - 1) << CNTL_TCT_SHIFT);
-
+
if (!(cntl & CNTL_RW))
for (j = 0; j < count; ++j)
out_8((void __iomem *)&iic->mdbuf, *buf++);
-
+
if (i < loops - 1)
cmd |= CNTL_CHT;
else if (combined_xfer)
cmd |= CNTL_RPST;
-
+
DBG2("%d: xfer_bytes, %d, CNTL = 0x%02x\n", dev->idx, count, cmd);
-
+
/* Start transfer */
out_8(&iic->cntl, cmd);
-
+
/* Wait for completion */
ret = iic_wait_for_tc(dev);
if (unlikely(ret < 0))
break;
else if (unlikely(ret != count)){
- DBG("%d: xfer_bytes, requested %d, transfered %d\n",
+ DBG("%d: xfer_bytes, requested %d, transfered %d\n",
dev->idx, count, ret);
-
+
/* If it's not a last part of xfer, abort it */
if (combined_xfer || (i < loops - 1))
iic_abort_xfer(dev);
-
+
ret = -EREMOTEIO;
- break;
+ break;
}
-
+
if (cntl & CNTL_RW)
for (j = 0; j < count; ++j)
*buf++ = in_8((void __iomem *)&iic->mdbuf);
}
-
+
return ret > 0 ? 0 : ret;
}
@@ -517,10 +517,10 @@ static inline void iic_address(struct ibm_iic_private* dev, struct i2c_msg* msg)
{
volatile struct iic_regs __iomem *iic = dev->vaddr;
u16 addr = msg->addr;
-
- DBG2("%d: iic_address, 0x%03x (%d-bit)\n", dev->idx,
+
+ DBG2("%d: iic_address, 0x%03x (%d-bit)\n", dev->idx,
addr, msg->flags & I2C_M_TEN ? 10 : 7);
-
+
if (msg->flags & I2C_M_TEN){
out_8(&iic->cntl, CNTL_AMD);
out_8(&iic->lmadr, addr);
@@ -537,15 +537,15 @@ static inline int iic_invalid_address(const struct i2c_msg* p)
return (p->addr > 0x3ff) || (!(p->flags & I2C_M_TEN) && (p->addr > 0x7f));
}
-static inline int iic_address_neq(const struct i2c_msg* p1,
+static inline int iic_address_neq(const struct i2c_msg* p1,
const struct i2c_msg* p2)
{
- return (p1->addr != p2->addr)
+ return (p1->addr != p2->addr)
|| ((p1->flags & I2C_M_TEN) != (p2->flags & I2C_M_TEN));
-}
+}
/*
- * Generic master transfer entrypoint.
+ * Generic master transfer entrypoint.
* Returns the number of processed messages or error (<0)
*/
static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
@@ -553,20 +553,20 @@ static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
struct ibm_iic_private* dev = (struct ibm_iic_private*)(i2c_get_adapdata(adap));
volatile struct iic_regs __iomem *iic = dev->vaddr;
int i, ret = 0;
-
+
DBG2("%d: iic_xfer, %d msg(s)\n", dev->idx, num);
-
+
if (!num)
return 0;
-
+
/* Check the sanity of the passed messages.
* Uhh, generic i2c layer is more suitable place for such code...
*/
if (unlikely(iic_invalid_address(&msgs[0]))){
- DBG("%d: invalid address 0x%03x (%d-bit)\n", dev->idx,
+ DBG("%d: invalid address 0x%03x (%d-bit)\n", dev->idx,
msgs[0].addr, msgs[0].flags & I2C_M_TEN ? 10 : 7);
return -EINVAL;
- }
+ }
for (i = 0; i < num; ++i){
if (unlikely(msgs[i].len <= 0)){
if (num == 1 && !msgs[0].len){
@@ -576,7 +576,7 @@ static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
*/
return iic_smbus_quick(dev, &msgs[0]);
}
- DBG("%d: invalid len %d in msg[%d]\n", dev->idx,
+ DBG("%d: invalid len %d in msg[%d]\n", dev->idx,
msgs[i].len, i);
return -EINVAL;
}
@@ -585,34 +585,34 @@ static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
return -EINVAL;
}
}
-
+
/* Check bus state */
if (unlikely((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE)){
DBG("%d: iic_xfer, bus is not free\n", dev->idx);
-
+
/* Usually it means something serious has happend.
* We *cannot* have unfinished previous transfer
* so it doesn't make any sense to try to stop it.
- * Probably we were not able to recover from the
+ * Probably we were not able to recover from the
* previous error.
* The only *reasonable* thing I can think of here
* is soft reset. --ebs
*/
iic_dev_reset(dev);
-
+
if ((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE){
DBG("%d: iic_xfer, bus is still not free\n", dev->idx);
return -EREMOTEIO;
}
- }
+ }
else {
/* Flush master data buffer (just in case) */
out_8(&iic->mdcntl, in_8(&iic->mdcntl) | MDCNTL_FMDB);
}
-
+
/* Load slave address */
iic_address(dev, &msgs[0]);
-
+
/* Do real transfer */
for (i = 0; i < num && !ret; ++i)
ret = iic_xfer_bytes(dev, &msgs[i], i < num - 1);
@@ -648,7 +648,7 @@ static inline u8 iic_clckdiv(unsigned int opb)
/* Convert to MHz */
opb /= 1000000;
-
+
if (opb < 20 || opb > 150){
printk(KERN_CRIT "ibm-iic: invalid OPB clock frequency %u MHz\n",
opb);
@@ -666,7 +666,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
struct i2c_adapter* adap;
struct ocp_func_iic_data* iic_data = ocp->def->additions;
int ret;
-
+
if (!iic_data)
printk(KERN_WARNING"ibm-iic%d: missing additional data!\n",
ocp->def->index);
@@ -679,7 +679,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
dev->idx = ocp->def->index;
ocp_set_drvdata(ocp, dev);
-
+
if (!request_mem_region(ocp->def->paddr, sizeof(struct iic_regs),
"ibm_iic")) {
ret = -EBUSY;
@@ -692,7 +692,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
ret = -ENXIO;
goto fail2;
}
-
+
init_waitqueue_head(&dev->wq);
dev->irq = iic_force_poll ? -1 : ocp->def->irq;
@@ -702,29 +702,29 @@ static int __devinit iic_probe(struct ocp_device *ocp){
*/
iic_interrupt_mode(dev, 0);
if (request_irq(dev->irq, iic_handler, 0, "IBM IIC", dev)){
- printk(KERN_ERR "ibm-iic%d: request_irq %d failed\n",
+ printk(KERN_ERR "ibm-iic%d: request_irq %d failed\n",
dev->idx, dev->irq);
- /* Fallback to the polling mode */
+ /* Fallback to the polling mode */
dev->irq = -1;
}
}
-
+
if (dev->irq < 0)
- printk(KERN_WARNING "ibm-iic%d: using polling mode\n",
+ printk(KERN_WARNING "ibm-iic%d: using polling mode\n",
dev->idx);
-
+
/* Board specific settings */
dev->fast_mode = iic_force_fast ? 1 : (iic_data ? iic_data->fast_mode : 0);
-
- /* clckdiv is the same for *all* IIC interfaces,
+
+ /* clckdiv is the same for *all* IIC interfaces,
* but I'd rather make a copy than introduce another global. --ebs
*/
dev->clckdiv = iic_clckdiv(ocp_sys_info.opb_bus_freq);
DBG("%d: clckdiv = %d\n", dev->idx, dev->clckdiv);
-
+
/* Initialize IIC interface */
iic_dev_init(dev);
-
+
/* Register it with i2c layer */
adap = &dev->adap;
adap->dev.parent = &ocp->dev;
@@ -736,7 +736,6 @@ static int __devinit iic_probe(struct ocp_device *ocp){
adap->client_register = NULL;
adap->client_unregister = NULL;
adap->timeout = 1;
- adap->retries = 1;
/*
* If "dev->idx" is negative we consider it as zero.
@@ -750,24 +749,24 @@ static int __devinit iic_probe(struct ocp_device *ocp){
dev->idx);
goto fail;
}
-
+
printk(KERN_INFO "ibm-iic%d: using %s mode\n", dev->idx,
dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");
return 0;
-fail:
+fail:
if (dev->irq >= 0){
iic_interrupt_mode(dev, 0);
free_irq(dev->irq, dev);
- }
+ }
iounmap(dev->vaddr);
-fail2:
+fail2:
release_mem_region(ocp->def->paddr, sizeof(struct iic_regs));
fail1:
ocp_set_drvdata(ocp, NULL);
- kfree(dev);
+ kfree(dev);
return ret;
}
@@ -783,13 +782,13 @@ static void __devexit iic_remove(struct ocp_device *ocp)
dev->idx);
/* That's *very* bad, just shutdown IRQ ... */
if (dev->irq >= 0){
- iic_interrupt_mode(dev, 0);
+ iic_interrupt_mode(dev, 0);
free_irq(dev->irq, dev);
dev->irq = -1;
}
} else {
if (dev->irq >= 0){
- iic_interrupt_mode(dev, 0);
+ iic_interrupt_mode(dev, 0);
free_irq(dev->irq, dev);
}
iounmap(dev->vaddr);
@@ -798,7 +797,7 @@ static void __devexit iic_remove(struct ocp_device *ocp)
}
}
-static struct ocp_device_id ibm_iic_ids[] __devinitdata =
+static struct ocp_device_id ibm_iic_ids[] __devinitdata =
{
{ .vendor = OCP_VENDOR_IBM, .function = OCP_FUNC_IIC },
{ .vendor = OCP_VENDOR_INVALID }
diff --git a/drivers/i2c/busses/i2c-ibm_iic.h b/drivers/i2c/busses/i2c-ibm_iic.h
index 59d7b437f7ff..fdaa48292cb6 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.h
+++ b/drivers/i2c/busses/i2c-ibm_iic.h
@@ -2,11 +2,11 @@
* drivers/i2c/busses/i2c-ibm_iic.h
*
* Support for the IIC peripheral on IBM PPC 4xx
- *
+ *
* Copyright (c) 2003 Zultys Technologies.
* Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
*
- * Based on original work by
+ * Based on original work by
* Ian DaSilva <idasilva@mvista.com>
* Armin Kuster <akuster@mvista.com>
* Matt Porter <mporter@mvista.com>
@@ -22,7 +22,7 @@
#ifndef __I2C_IBM_IIC_H_
#define __I2C_IBM_IIC_H_
-#include <linux/i2c.h>
+#include <linux/i2c.h>
struct iic_regs {
u16 mdbuf;
@@ -58,7 +58,7 @@ struct ibm_iic_private {
#define CNTL_TCT_MASK 0x30
#define CNTL_TCT_SHIFT 4
#define CNTL_RPST 0x08
-#define CNTL_CHT 0x04
+#define CNTL_CHT 0x04
#define CNTL_RW 0x02
#define CNTL_PT 0x01
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index c70146e4c2c0..ab41400c883e 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -490,7 +490,6 @@ iop3xx_i2c_probe(struct platform_device *pdev)
* Default values...should these come in from board code?
*/
new_adapter->timeout = 100;
- new_adapter->retries = 3;
new_adapter->algo = &iop3xx_i2c_algo;
init_waitqueue_head(&adapter_data->waitq);
diff --git a/drivers/i2c/busses/i2c-ixp4xx.c b/drivers/i2c/busses/i2c-ixp4xx.c
deleted file mode 100644
index 069ed7f3b395..000000000000
--- a/drivers/i2c/busses/i2c-ixp4xx.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * drivers/i2c/busses/i2c-ixp4xx.c
- *
- * Intel's IXP4xx XScale NPU chipsets (IXP420, 421, 422, 425) do not have
- * an on board I2C controller but provide 16 GPIO pins that are often
- * used to create an I2C bus. This driver provides an i2c_adapter
- * interface that plugs in under algo_bit and drives the GPIO pins
- * as instructed by the alogorithm driver.
- *
- * Author: Deepak Saxena <dsaxena@plexity.net>
- *
- * Copyright (c) 2003-2004 MontaVista Software Inc.
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- *
- * NOTE: Since different platforms will use different GPIO pins for
- * I2C, this driver uses an IXP4xx-specific platform_data
- * pointer to pass the GPIO numbers to the driver. This
- * allows us to support all the different IXP4xx platforms
- * w/o having to put #ifdefs in this driver.
- *
- * See arch/arm/mach-ixp4xx/ixdp425.c for an example of building a
- * device list and filling in the ixp4xx_i2c_pins data structure
- * that is passed as the platform_data to this driver.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-
-#include <asm/hardware.h> /* Pick up IXP4xx-specific bits */
-
-static inline int ixp4xx_scl_pin(void *data)
-{
- return ((struct ixp4xx_i2c_pins*)data)->scl_pin;
-}
-
-static inline int ixp4xx_sda_pin(void *data)
-{
- return ((struct ixp4xx_i2c_pins*)data)->sda_pin;
-}
-
-static void ixp4xx_bit_setscl(void *data, int val)
-{
- gpio_line_set(ixp4xx_scl_pin(data), 0);
- gpio_line_config(ixp4xx_scl_pin(data),
- val ? IXP4XX_GPIO_IN : IXP4XX_GPIO_OUT );
-}
-
-static void ixp4xx_bit_setsda(void *data, int val)
-{
- gpio_line_set(ixp4xx_sda_pin(data), 0);
- gpio_line_config(ixp4xx_sda_pin(data),
- val ? IXP4XX_GPIO_IN : IXP4XX_GPIO_OUT );
-}
-
-static int ixp4xx_bit_getscl(void *data)
-{
- int scl;
-
- gpio_line_config(ixp4xx_scl_pin(data), IXP4XX_GPIO_IN );
- gpio_line_get(ixp4xx_scl_pin(data), &scl);
-
- return scl;
-}
-
-static int ixp4xx_bit_getsda(void *data)
-{
- int sda;
-
- gpio_line_config(ixp4xx_sda_pin(data), IXP4XX_GPIO_IN );
- gpio_line_get(ixp4xx_sda_pin(data), &sda);
-
- return sda;
-}
-
-struct ixp4xx_i2c_data {
- struct ixp4xx_i2c_pins *gpio_pins;
- struct i2c_adapter adapter;
- struct i2c_algo_bit_data algo_data;
-};
-
-static int ixp4xx_i2c_remove(struct platform_device *plat_dev)
-{
- struct ixp4xx_i2c_data *drv_data = platform_get_drvdata(plat_dev);
-
- platform_set_drvdata(plat_dev, NULL);
-
- i2c_del_adapter(&drv_data->adapter);
-
- kfree(drv_data);
-
- return 0;
-}
-
-static int ixp4xx_i2c_probe(struct platform_device *plat_dev)
-{
- int err;
- struct ixp4xx_i2c_pins *gpio = plat_dev->dev.platform_data;
- struct ixp4xx_i2c_data *drv_data =
- kzalloc(sizeof(struct ixp4xx_i2c_data), GFP_KERNEL);
-
- if(!drv_data)
- return -ENOMEM;
-
- drv_data->gpio_pins = gpio;
-
- /*
- * We could make a lot of these structures static, but
- * certain platforms may have multiple GPIO-based I2C
- * buses for various device domains, so we need per-device
- * algo_data->data.
- */
- drv_data->algo_data.data = gpio;
- drv_data->algo_data.setsda = ixp4xx_bit_setsda;
- drv_data->algo_data.setscl = ixp4xx_bit_setscl;
- drv_data->algo_data.getsda = ixp4xx_bit_getsda;
- drv_data->algo_data.getscl = ixp4xx_bit_getscl;
- drv_data->algo_data.udelay = 10;
- 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,
- sizeof(drv_data->adapter.name));
- drv_data->adapter.algo_data = &drv_data->algo_data;
-
- drv_data->adapter.dev.parent = &plat_dev->dev;
-
- gpio_line_config(gpio->scl_pin, IXP4XX_GPIO_IN);
- gpio_line_config(gpio->sda_pin, IXP4XX_GPIO_IN);
- gpio_line_set(gpio->scl_pin, 0);
- gpio_line_set(gpio->sda_pin, 0);
-
- err = i2c_bit_add_bus(&drv_data->adapter);
- if (err) {
- printk(KERN_ERR "ERROR: Could not install %s\n", plat_dev->dev.bus_id);
-
- kfree(drv_data);
- return err;
- }
-
- platform_set_drvdata(plat_dev, drv_data);
-
- return 0;
-}
-
-static struct platform_driver ixp4xx_i2c_driver = {
- .probe = ixp4xx_i2c_probe,
- .remove = ixp4xx_i2c_remove,
- .driver = {
- .name = "IXP4XX-I2C",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init ixp4xx_i2c_init(void)
-{
- return platform_driver_register(&ixp4xx_i2c_driver);
-}
-
-static void __exit ixp4xx_i2c_exit(void)
-{
- platform_driver_unregister(&ixp4xx_i2c_driver);
-}
-
-module_init(ixp4xx_i2c_init);
-module_exit(ixp4xx_i2c_exit);
-
-MODULE_DESCRIPTION("GPIO-based I2C adapter for IXP4xx systems");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
-
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index d8de4ac88b7d..bbe787b243b7 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -180,7 +180,7 @@ static void mpc_i2c_stop(struct mpc_i2c *i2c)
static int mpc_write(struct mpc_i2c *i2c, int target,
const u8 * data, int length, int restart)
{
- int i;
+ int i, result;
unsigned timeout = i2c->adap.timeout;
u32 flags = restart ? CCR_RSTA : 0;
@@ -192,15 +192,17 @@ static int mpc_write(struct mpc_i2c *i2c, int target,
/* Write target byte */
writeb((target << 1), i2c->base + MPC_I2C_DR);
- if (i2c_wait(i2c, timeout, 1) < 0)
- return -1;
+ result = i2c_wait(i2c, timeout, 1);
+ if (result < 0)
+ return result;
for (i = 0; i < length; i++) {
/* Write data byte */
writeb(data[i], i2c->base + MPC_I2C_DR);
- if (i2c_wait(i2c, timeout, 1) < 0)
- return -1;
+ result = i2c_wait(i2c, timeout, 1);
+ if (result < 0)
+ return result;
}
return 0;
@@ -210,7 +212,7 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
u8 * data, int length, int restart)
{
unsigned timeout = i2c->adap.timeout;
- int i;
+ int i, result;
u32 flags = restart ? CCR_RSTA : 0;
/* Start with MEN */
@@ -221,8 +223,9 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
/* Write target address byte - this time with the read flag set */
writeb((target << 1) | 1, i2c->base + MPC_I2C_DR);
- if (i2c_wait(i2c, timeout, 1) < 0)
- return -1;
+ result = i2c_wait(i2c, timeout, 1);
+ if (result < 0)
+ return result;
if (length) {
if (length == 1)
@@ -234,8 +237,9 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
}
for (i = 0; i < length; i++) {
- if (i2c_wait(i2c, timeout, 0) < 0)
- return -1;
+ result = i2c_wait(i2c, timeout, 0);
+ if (result < 0)
+ return result;
/* Generate txack on next to last byte */
if (i == length - 2)
@@ -309,7 +313,6 @@ static struct i2c_adapter mpc_ops = {
.algo = &mpc_algo,
.class = I2C_CLASS_HWMON,
.timeout = 1,
- .retries = 1
};
static int fsl_i2c_probe(struct platform_device *pdev)
@@ -321,9 +324,9 @@ static int fsl_i2c_probe(struct platform_device *pdev)
pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data;
- if (!(i2c = kzalloc(sizeof(*i2c), GFP_KERNEL))) {
+ i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
+ if (!i2c)
return -ENOMEM;
- }
i2c->irq = platform_get_irq(pdev, 0);
if (i2c->irq < 0) {
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index 1bf590c74166..3dac920e53ea 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -351,6 +351,7 @@ static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_
pci_set_drvdata(dev, smbuses);
switch(dev->device) {
+ case PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS:
case PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS:
case PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS:
smbuses[0].blockops = 1;
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index f2552b19ea60..da6639707ea3 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -362,8 +362,6 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
omap_i2c_enable_clocks(dev);
- /* REVISIT: initialize and use adap->retries. This is an optional
- * feature */
if ((r = omap_i2c_wait_for_bb(dev)) < 0)
goto out;
diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c
index ca18e0be4901..1603c81e39d4 100644
--- a/drivers/i2c/busses/i2c-pasemi.c
+++ b/drivers/i2c/busses/i2c-pasemi.c
@@ -368,6 +368,7 @@ static int __devinit pasemi_smb_probe(struct pci_dev *dev,
smbus->adapter.class = I2C_CLASS_HWMON;
smbus->adapter.algo = &smbus_algorithm;
smbus->adapter.algo_data = smbus;
+ smbus->adapter.nr = PCI_FUNC(dev->devfn);
/* set up the sysfs linkage to our parent device */
smbus->adapter.dev.parent = &dev->dev;
@@ -375,7 +376,7 @@ static int __devinit pasemi_smb_probe(struct pci_dev *dev,
reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR |
(CLK_100K_DIV & CTL_CLK_M)));
- error = i2c_add_adapter(&smbus->adapter);
+ error = i2c_add_numbered_adapter(&smbus->adapter);
if (error)
goto out_release_region;
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 167e4137ee21..9bbe96cef719 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -121,10 +121,6 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
{
unsigned char temp;
- /* match up the function */
- if (PCI_FUNC(PIIX4_dev->devfn) != id->driver_data)
- return -ENODEV;
-
dev_info(&PIIX4_dev->dev, "Found %s device\n", pci_name(PIIX4_dev));
/* Don't access SMBus on IBM systems which get corrupted eeproms */
@@ -389,28 +385,21 @@ static struct i2c_adapter piix4_adapter = {
};
static struct pci_device_id piix4_ids[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3),
- .driver_data = 3 },
- { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_SMBUS),
- .driver_data = 0 },
- { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_SMBUS),
- .driver_data = 0 },
- { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS),
- .driver_data = 0 },
- { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS),
- .driver_data = 0 },
- { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4),
- .driver_data = 0 },
- { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5),
- .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),
- .driver_data = 0 },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3) },
+ { PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
+ PCI_DEVICE_ID_SERVERWORKS_OSB4) },
+ { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
+ PCI_DEVICE_ID_SERVERWORKS_CSB5) },
+ { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
+ PCI_DEVICE_ID_SERVERWORKS_CSB6) },
+ { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
+ PCI_DEVICE_ID_SERVERWORKS_HT1000SB) },
{ 0, }
};
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index 6426a61f8d4d..2598d29fd7a4 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -65,6 +65,7 @@ struct pxa_i2c {
unsigned long iosize;
int irq;
+ int use_pio;
};
#define _IBMR(i2c) ((i2c)->reg_base + 0)
@@ -163,6 +164,7 @@ static void i2c_pxa_show_state(struct pxa_i2c *i2c, int lno, const char *fname)
#define eedbg(lvl, x...) do { if ((lvl) < 1) { printk(KERN_DEBUG "" x); } } while(0)
static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret);
+static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id);
static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why)
{
@@ -554,6 +556,71 @@ static inline void i2c_pxa_stop_message(struct pxa_i2c *i2c)
writel(icr, _ICR(i2c));
}
+static int i2c_pxa_pio_set_master(struct pxa_i2c *i2c)
+{
+ /* make timeout the same as for interrupt based functions */
+ long timeout = 2 * DEF_TIMEOUT;
+
+ /*
+ * Wait for the bus to become free.
+ */
+ while (timeout-- && readl(_ISR(i2c)) & (ISR_IBB | ISR_UB)) {
+ udelay(1000);
+ show_state(i2c);
+ }
+
+ if (timeout <= 0) {
+ show_state(i2c);
+ dev_err(&i2c->adap.dev,
+ "i2c_pxa: timeout waiting for bus free\n");
+ return I2C_RETRY;
+ }
+
+ /*
+ * Set master mode.
+ */
+ writel(readl(_ICR(i2c)) | ICR_SCLE, _ICR(i2c));
+
+ return 0;
+}
+
+static int i2c_pxa_do_pio_xfer(struct pxa_i2c *i2c,
+ struct i2c_msg *msg, int num)
+{
+ unsigned long timeout = 500000; /* 5 seconds */
+ int ret = 0;
+
+ ret = i2c_pxa_pio_set_master(i2c);
+ if (ret)
+ goto out;
+
+ i2c->msg = msg;
+ i2c->msg_num = num;
+ i2c->msg_idx = 0;
+ i2c->msg_ptr = 0;
+ i2c->irqlogidx = 0;
+
+ i2c_pxa_start_message(i2c);
+
+ while (timeout-- && i2c->msg_num > 0) {
+ i2c_pxa_handler(0, i2c);
+ udelay(10);
+ }
+
+ i2c_pxa_stop_message(i2c);
+
+ /*
+ * We place the return code in i2c->msg_idx.
+ */
+ ret = i2c->msg_idx;
+
+out:
+ if (timeout == 0)
+ i2c_pxa_scream_blue_murder(i2c, "timeout");
+
+ return ret;
+}
+
/*
* We are protected by the adapter bus mutex.
*/
@@ -610,6 +677,35 @@ static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num)
return ret;
}
+static int i2c_pxa_pio_xfer(struct i2c_adapter *adap,
+ struct i2c_msg msgs[], int num)
+{
+ struct pxa_i2c *i2c = adap->algo_data;
+ int ret, i;
+
+ /* If the I2C controller is disabled we need to reset it
+ (probably due to a suspend/resume destroying state). We do
+ this here as we can then avoid worrying about resuming the
+ controller before its users. */
+ if (!(readl(_ICR(i2c)) & ICR_IUE))
+ i2c_pxa_reset(i2c);
+
+ for (i = adap->retries; i >= 0; i--) {
+ ret = i2c_pxa_do_pio_xfer(i2c, msgs, num);
+ if (ret != I2C_RETRY)
+ goto out;
+
+ if (i2c_debug)
+ dev_dbg(&adap->dev, "Retrying transmission\n");
+ udelay(100);
+ }
+ i2c_pxa_scream_blue_murder(i2c, "exhausted retries");
+ ret = -EREMOTEIO;
+ out:
+ i2c_pxa_set_slave(i2c, ret);
+ return ret;
+}
+
/*
* i2c_pxa_master_complete - complete the message and wake up.
*/
@@ -621,7 +717,8 @@ static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret)
i2c->msg_num = 0;
if (ret)
i2c->msg_idx = ret;
- wake_up(&i2c->wait);
+ if (!i2c->use_pio)
+ wake_up(&i2c->wait);
}
static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr)
@@ -840,6 +937,37 @@ static const struct i2c_algorithm i2c_pxa_algorithm = {
.functionality = i2c_pxa_functionality,
};
+static const struct i2c_algorithm i2c_pxa_pio_algorithm = {
+ .master_xfer = i2c_pxa_pio_xfer,
+ .functionality = i2c_pxa_functionality,
+};
+
+static void i2c_pxa_enable(struct platform_device *dev)
+{
+ if (cpu_is_pxa27x()) {
+ switch (dev->id) {
+ case 0:
+ pxa_gpio_mode(GPIO117_I2CSCL_MD);
+ pxa_gpio_mode(GPIO118_I2CSDA_MD);
+ break;
+ case 1:
+ local_irq_disable();
+ PCFR |= PCFR_PI2CEN;
+ local_irq_enable();
+ break;
+ }
+ }
+}
+
+static void i2c_pxa_disable(struct platform_device *dev)
+{
+ if (cpu_is_pxa27x() && dev->id == 1) {
+ local_irq_disable();
+ PCFR &= ~PCFR_PI2CEN;
+ local_irq_enable();
+ }
+}
+
#define res_len(r) ((r)->end - (r)->start + 1)
static int i2c_pxa_probe(struct platform_device *dev)
{
@@ -864,7 +992,6 @@ static int i2c_pxa_probe(struct platform_device *dev)
}
i2c->adap.owner = THIS_MODULE;
- i2c->adap.algo = &i2c_pxa_algorithm;
i2c->adap.retries = 5;
spin_lock_init(&i2c->lock);
@@ -899,34 +1026,28 @@ static int i2c_pxa_probe(struct platform_device *dev)
#endif
clk_enable(i2c->clk);
-#ifdef CONFIG_PXA27x
- switch (dev->id) {
- case 0:
- pxa_gpio_mode(GPIO117_I2CSCL_MD);
- pxa_gpio_mode(GPIO118_I2CSDA_MD);
- break;
- case 1:
- local_irq_disable();
- PCFR |= PCFR_PI2CEN;
- local_irq_enable();
- }
-#endif
+ i2c_pxa_enable(dev);
- ret = request_irq(irq, i2c_pxa_handler, IRQF_DISABLED,
- i2c->adap.name, i2c);
- if (ret)
- goto ereqirq;
+ if (plat) {
+ i2c->adap.class = plat->class;
+ i2c->use_pio = plat->use_pio;
+ }
+ if (i2c->use_pio) {
+ i2c->adap.algo = &i2c_pxa_pio_algorithm;
+ } else {
+ i2c->adap.algo = &i2c_pxa_algorithm;
+ ret = request_irq(irq, i2c_pxa_handler, IRQF_DISABLED,
+ i2c->adap.name, i2c);
+ if (ret)
+ goto ereqirq;
+ }
i2c_pxa_reset(i2c);
i2c->adap.algo_data = i2c;
i2c->adap.dev.parent = &dev->dev;
- if (plat) {
- i2c->adap.class = plat->class;
- }
-
/*
* If "dev->id" is negative we consider it as zero.
* The reason to do so is to avoid sysfs names that only make
@@ -952,17 +1073,11 @@ static int i2c_pxa_probe(struct platform_device *dev)
return 0;
eadapt:
- free_irq(irq, i2c);
+ if (!i2c->use_pio)
+ free_irq(irq, i2c);
ereqirq:
clk_disable(i2c->clk);
-
-#ifdef CONFIG_PXA27x
- if (dev->id == 1) {
- local_irq_disable();
- PCFR &= ~PCFR_PI2CEN;
- local_irq_enable();
- }
-#endif
+ i2c_pxa_disable(dev);
eremap:
clk_put(i2c->clk);
eclk:
@@ -979,18 +1094,12 @@ static int i2c_pxa_remove(struct platform_device *dev)
platform_set_drvdata(dev, NULL);
i2c_del_adapter(&i2c->adap);
- free_irq(i2c->irq, i2c);
+ if (!i2c->use_pio)
+ free_irq(i2c->irq, i2c);
clk_disable(i2c->clk);
clk_put(i2c->clk);
-
-#ifdef CONFIG_PXA27x
- if (dev->id == 1) {
- local_irq_disable();
- PCFR &= ~PCFR_PI2CEN;
- local_irq_enable();
- }
-#endif
+ i2c_pxa_disable(dev);
release_mem_region(i2c->iobase, i2c->iosize);
kfree(i2c);
diff --git a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c
index 503a134ec803..8fbbdb4c2f35 100644
--- a/drivers/i2c/busses/i2c-sibyte.c
+++ b/drivers/i2c/busses/i2c-sibyte.c
@@ -36,14 +36,6 @@ struct i2c_algo_sibyte_data {
/* ----- global defines ----------------------------------------------- */
#define SMB_CSR(a,r) ((long)(a->reg_base + r))
-/* ----- global variables --------------------------------------------- */
-
-/* module parameters:
- */
-static int bit_scan; /* have a look at what's hanging 'round */
-module_param(bit_scan, int, 0);
-MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus");
-
static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr,
unsigned short flags, char read_write,
@@ -140,9 +132,8 @@ static const struct i2c_algorithm i2c_sibyte_algo = {
/*
* registering functions to load algorithms at runtime
*/
-int i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
+int __init i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
{
- int i;
struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
/* register new adapter to i2c module... */
@@ -152,24 +143,6 @@ int i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
csr_out32(speed, SMB_CSR(adap,R_SMB_FREQ));
csr_out32(0, SMB_CSR(adap,R_SMB_CONTROL));
- /* scan bus */
- if (bit_scan) {
- union i2c_smbus_data data;
- int rc;
- printk(KERN_INFO " i2c-algo-sibyte.o: scanning bus %s.\n",
- i2c_adap->name);
- for (i = 0x00; i < 0x7f; i++) {
- /* XXXKW is this a realistic probe? */
- rc = smbus_xfer(i2c_adap, i, 0, I2C_SMBUS_READ, 0,
- I2C_SMBUS_BYTE_DATA, &data);
- if (!rc) {
- printk("(%02x)",i);
- } else
- printk(".");
- }
- printk("\n");
- }
-
return i2c_add_adapter(i2c_adap);
}
diff --git a/drivers/i2c/busses/i2c-stub.c b/drivers/i2c/busses/i2c-stub.c
index 84df29da1ddc..c2a9f8c94f5e 100644
--- a/drivers/i2c/busses/i2c-stub.c
+++ b/drivers/i2c/busses/i2c-stub.c
@@ -1,8 +1,8 @@
/*
- i2c-stub.c - Part of lm_sensors, Linux kernel modules for hardware
- monitoring
+ i2c-stub.c - I2C/SMBus chip emulator
Copyright (c) 2004 Mark M. Hoffman <mhoffman@lightlink.com>
+ Copyright (C) 2007 Jean Delvare <khali@linux-fr.org>
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
@@ -37,8 +37,8 @@ MODULE_PARM_DESC(chip_addr,
struct stub_chip {
u8 pointer;
- u8 bytes[256];
- u16 words[256];
+ u16 words[256]; /* Byte operations use the LSB as per SMBus
+ specification */
};
static struct stub_chip *stub_chips;
@@ -75,7 +75,7 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
"wrote 0x%02x.\n",
addr, command);
} else {
- data->byte = chip->bytes[chip->pointer++];
+ data->byte = chip->words[chip->pointer++] & 0xff;
dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, "
"read 0x%02x.\n",
addr, data->byte);
@@ -86,12 +86,13 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
case I2C_SMBUS_BYTE_DATA:
if (read_write == I2C_SMBUS_WRITE) {
- chip->bytes[command] = data->byte;
+ chip->words[command] &= 0xff00;
+ chip->words[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 = chip->bytes[command];
+ data->byte = chip->words[command] & 0xff;
dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, "
"read 0x%02x at 0x%02x.\n",
addr, data->byte, command);
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index c9ce77f13c0e..77b13d027f86 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -4,7 +4,7 @@
Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>,
Philip Edelbrock <phil@netroedge.com>, Kyösti Mälkki <kmalkki@cc.hut.fi>,
Mark D. Studebaker <mdsxyz123@yahoo.com>
- Copyright (C) 2005 - 2007 Jean Delvare <khali@linux-fr.org>
+ Copyright (C) 2005 - 2008 Jean Delvare <khali@linux-fr.org>
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
@@ -35,6 +35,7 @@
VT8235 0x3177 yes
VT8237R 0x3227 yes
VT8237A 0x3337 yes
+ VT8237S 0x3372 yes
VT8251 0x3287 yes
CX700 0x8324 yes
@@ -318,6 +319,10 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
unsigned char temp;
int error = -ENODEV;
+ /* driver_data might come from user-space, so check it */
+ if (id->driver_data & 1 || id->driver_data > 0xff)
+ return -EINVAL;
+
/* Determine the address of the SMBus areas */
if (force_addr) {
vt596_smba = force_addr & 0xfff0;
@@ -389,6 +394,7 @@ found:
case PCI_DEVICE_ID_VIA_8251:
case PCI_DEVICE_ID_VIA_8237:
case PCI_DEVICE_ID_VIA_8237A:
+ case PCI_DEVICE_ID_VIA_8237S:
case PCI_DEVICE_ID_VIA_8235:
case PCI_DEVICE_ID_VIA_8233A:
case PCI_DEVICE_ID_VIA_8233_0:
@@ -440,6 +446,8 @@ static struct pci_device_id vt596_ids[] = {
.driver_data = SMBBA3 },
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237A),
.driver_data = SMBBA3 },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237S),
+ .driver_data = SMBBA3 },
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4),
.driver_data = SMBBA1 },
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8251),
@@ -455,6 +463,7 @@ static struct pci_driver vt596_driver = {
.name = "vt596_smbus",
.id_table = vt596_ids,
.probe = vt596_probe,
+ .dynids.use_driver_data = 1,
};
static int __init i2c_vt596_init(void)
OpenPOWER on IntegriCloud