diff options
Diffstat (limited to 'drivers/i2c')
27 files changed, 1992 insertions, 289 deletions
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 30f06e956bfb..b923074b2cbe 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -75,7 +75,8 @@ config I2C_HELPER_AUTO In doubt, say Y. config I2C_SMBUS - tristate "SMBus-specific protocols" if !I2C_HELPER_AUTO + tristate + prompt "SMBus-specific protocols" if !I2C_HELPER_AUTO help Say Y here if you want support for SMBus extensions to the I2C specification. At the moment, the only supported extension is diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index c00fd66388f5..23ac61e2db39 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -9,6 +9,4 @@ obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o obj-$(CONFIG_I2C_MUX) += i2c-mux.o obj-y += algos/ busses/ muxes/ -ifeq ($(CONFIG_I2C_DEBUG_CORE),y) -EXTRA_CFLAGS += -DDEBUG -endif +ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG diff --git a/drivers/i2c/algos/Kconfig b/drivers/i2c/algos/Kconfig index 7b2ce4a08524..3998dd620a03 100644 --- a/drivers/i2c/algos/Kconfig +++ b/drivers/i2c/algos/Kconfig @@ -15,3 +15,15 @@ config I2C_ALGOPCA tristate "I2C PCA 9564 interfaces" endmenu + +# In automatic configuration mode, we still have to define the +# symbols to avoid unmet dependencies. + +if I2C_HELPER_AUTO +config I2C_ALGOBIT + tristate +config I2C_ALGOPCF + tristate +config I2C_ALGOPCA + tristate +endif diff --git a/drivers/i2c/algos/Makefile b/drivers/i2c/algos/Makefile index 18b3e962ec09..215303f60d61 100644 --- a/drivers/i2c/algos/Makefile +++ b/drivers/i2c/algos/Makefile @@ -6,6 +6,4 @@ obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bit.o obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.o obj-$(CONFIG_I2C_ALGOPCA) += i2c-algo-pca.o -ifeq ($(CONFIG_I2C_DEBUG_ALGO),y) -EXTRA_CFLAGS += -DDEBUG -endif +ccflags-$(CONFIG_I2C_DEBUG_ALGO) := -DDEBUG diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 6539ac2907e9..3a6321cb8030 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -95,10 +95,11 @@ config I2C_I801 ESB2 ICH8 ICH9 - Tolapai + EP80579 (Tolapai) ICH10 - 3400/5 Series (PCH) + 5/3400 Series (PCH) Cougar Point (PCH) + Patsburg (PCH) This driver can also be built as a module. If so, the module will be called i2c-i801. @@ -396,6 +397,16 @@ config I2C_IMX This driver can also be built as a module. If so, the module will be called i2c-imx. +config I2C_INTEL_MID + tristate "Intel Moorestown/Medfield Platform I2C controller" + depends on PCI + help + Say Y here if you have an Intel Moorestown/Medfield platform I2C + controller. + + This support is also available as a module. If so, the module + will be called i2c-intel-mid. + config I2C_IOP3XX tristate "Intel IOPx3xx and IXP4xx on-chip I2C interface" depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX || ARCH_IOP13XX diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index c3ef49230cba..84cb16ae6f9e 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o obj-$(CONFIG_I2C_IMX) += i2c-imx.o +obj-$(CONFIG_I2C_INTEL_MID) += i2c-intel-mid.o obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o obj-$(CONFIG_I2C_MPC) += i2c-mpc.o @@ -76,6 +77,4 @@ obj-$(CONFIG_I2C_STUB) += i2c-stub.o obj-$(CONFIG_SCx200_ACB) += scx200_acb.o obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o -ifeq ($(CONFIG_I2C_DEBUG_BUS),y) -EXTRA_CFLAGS += -DDEBUG -endif +ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c index af1e5e254b7b..6b6a6b1d7025 100644 --- a/drivers/i2c/busses/i2c-amd8111.c +++ b/drivers/i2c/busses/i2c-amd8111.c @@ -69,7 +69,7 @@ static struct pci_driver amd8111_driver; * ACPI 2.0 chapter 13 access of registers of the EC */ -static unsigned int amd_ec_wait_write(struct amd_smbus *smbus) +static int amd_ec_wait_write(struct amd_smbus *smbus) { int timeout = 500; @@ -85,7 +85,7 @@ static unsigned int amd_ec_wait_write(struct amd_smbus *smbus) return 0; } -static unsigned int amd_ec_wait_read(struct amd_smbus *smbus) +static int amd_ec_wait_read(struct amd_smbus *smbus) { int timeout = 500; @@ -101,7 +101,7 @@ static unsigned int amd_ec_wait_read(struct amd_smbus *smbus) return 0; } -static unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address, +static int amd_ec_read(struct amd_smbus *smbus, unsigned char address, unsigned char *data) { int status; @@ -124,7 +124,7 @@ static unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address, return 0; } -static unsigned int amd_ec_write(struct amd_smbus *smbus, unsigned char address, +static int amd_ec_write(struct amd_smbus *smbus, unsigned char address, unsigned char data) { int status; @@ -196,7 +196,7 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, { struct amd_smbus *smbus = adap->algo_data; unsigned char protocol, len, pec, temp[2]; - int i; + int i, status; protocol = (read_write == I2C_SMBUS_READ) ? AMD_SMB_PRTCL_READ : AMD_SMB_PRTCL_WRITE; @@ -209,38 +209,62 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, break; case I2C_SMBUS_BYTE: - if (read_write == I2C_SMBUS_WRITE) - amd_ec_write(smbus, AMD_SMB_CMD, command); + if (read_write == I2C_SMBUS_WRITE) { + status = amd_ec_write(smbus, AMD_SMB_CMD, + command); + if (status) + return status; + } protocol |= AMD_SMB_PRTCL_BYTE; break; case I2C_SMBUS_BYTE_DATA: - amd_ec_write(smbus, AMD_SMB_CMD, command); - if (read_write == I2C_SMBUS_WRITE) - amd_ec_write(smbus, AMD_SMB_DATA, data->byte); + status = amd_ec_write(smbus, AMD_SMB_CMD, command); + if (status) + return status; + if (read_write == I2C_SMBUS_WRITE) { + status = amd_ec_write(smbus, AMD_SMB_DATA, + data->byte); + if (status) + return status; + } protocol |= AMD_SMB_PRTCL_BYTE_DATA; break; case I2C_SMBUS_WORD_DATA: - amd_ec_write(smbus, AMD_SMB_CMD, command); + status = amd_ec_write(smbus, AMD_SMB_CMD, command); + if (status) + return status; if (read_write == I2C_SMBUS_WRITE) { - amd_ec_write(smbus, AMD_SMB_DATA, - data->word & 0xff); - amd_ec_write(smbus, AMD_SMB_DATA + 1, - data->word >> 8); + status = amd_ec_write(smbus, AMD_SMB_DATA, + data->word & 0xff); + if (status) + return status; + status = amd_ec_write(smbus, AMD_SMB_DATA + 1, + data->word >> 8); + if (status) + return status; } protocol |= AMD_SMB_PRTCL_WORD_DATA | pec; break; case I2C_SMBUS_BLOCK_DATA: - amd_ec_write(smbus, AMD_SMB_CMD, command); + status = amd_ec_write(smbus, AMD_SMB_CMD, command); + if (status) + return status; if (read_write == I2C_SMBUS_WRITE) { len = min_t(u8, data->block[0], I2C_SMBUS_BLOCK_MAX); - amd_ec_write(smbus, AMD_SMB_BCNT, len); - for (i = 0; i < len; i++) - amd_ec_write(smbus, AMD_SMB_DATA + i, - data->block[i + 1]); + status = amd_ec_write(smbus, AMD_SMB_BCNT, len); + if (status) + return status; + for (i = 0; i < len; i++) { + status = + amd_ec_write(smbus, AMD_SMB_DATA + i, + data->block[i + 1]); + if (status) + return status; + } } protocol |= AMD_SMB_PRTCL_BLOCK_DATA | pec; break; @@ -248,19 +272,35 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, case I2C_SMBUS_I2C_BLOCK_DATA: len = min_t(u8, data->block[0], I2C_SMBUS_BLOCK_MAX); - amd_ec_write(smbus, AMD_SMB_CMD, command); - amd_ec_write(smbus, AMD_SMB_BCNT, len); + status = amd_ec_write(smbus, AMD_SMB_CMD, command); + if (status) + return status; + status = amd_ec_write(smbus, AMD_SMB_BCNT, len); + if (status) + return status; if (read_write == I2C_SMBUS_WRITE) - for (i = 0; i < len; i++) - amd_ec_write(smbus, AMD_SMB_DATA + i, - data->block[i + 1]); + for (i = 0; i < len; i++) { + status = + amd_ec_write(smbus, AMD_SMB_DATA + i, + data->block[i + 1]); + if (status) + return status; + } protocol |= AMD_SMB_PRTCL_I2C_BLOCK_DATA; break; case I2C_SMBUS_PROC_CALL: - amd_ec_write(smbus, AMD_SMB_CMD, command); - amd_ec_write(smbus, AMD_SMB_DATA, data->word & 0xff); - amd_ec_write(smbus, AMD_SMB_DATA + 1, data->word >> 8); + status = amd_ec_write(smbus, AMD_SMB_CMD, command); + if (status) + return status; + status = amd_ec_write(smbus, AMD_SMB_DATA, + data->word & 0xff); + if (status) + return status; + status = amd_ec_write(smbus, AMD_SMB_DATA + 1, + data->word >> 8); + if (status) + return status; protocol = AMD_SMB_PRTCL_PROC_CALL | pec; read_write = I2C_SMBUS_READ; break; @@ -268,11 +308,18 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, case I2C_SMBUS_BLOCK_PROC_CALL: len = min_t(u8, data->block[0], I2C_SMBUS_BLOCK_MAX - 1); - amd_ec_write(smbus, AMD_SMB_CMD, command); - amd_ec_write(smbus, AMD_SMB_BCNT, len); - for (i = 0; i < len; i++) - amd_ec_write(smbus, AMD_SMB_DATA + i, - data->block[i + 1]); + status = amd_ec_write(smbus, AMD_SMB_CMD, command); + if (status) + return status; + status = amd_ec_write(smbus, AMD_SMB_BCNT, len); + if (status) + return status; + for (i = 0; i < len; i++) { + status = amd_ec_write(smbus, AMD_SMB_DATA + i, + data->block[i + 1]); + if (status) + return status; + } protocol = AMD_SMB_PRTCL_BLOCK_PROC_CALL | pec; read_write = I2C_SMBUS_READ; break; @@ -282,24 +329,29 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, return -EOPNOTSUPP; } - amd_ec_write(smbus, AMD_SMB_ADDR, addr << 1); - amd_ec_write(smbus, AMD_SMB_PRTCL, protocol); + status = amd_ec_write(smbus, AMD_SMB_ADDR, addr << 1); + if (status) + return status; + status = amd_ec_write(smbus, AMD_SMB_PRTCL, protocol); + if (status) + return status; - /* FIXME this discards status from ec_read(); so temp[0] will - * hold stack garbage ... the rest of this routine will act - * nonsensically. Ignored ec_write() status might explain - * some such failures... - */ - amd_ec_read(smbus, AMD_SMB_STS, temp + 0); + status = amd_ec_read(smbus, AMD_SMB_STS, temp + 0); + if (status) + return status; if (~temp[0] & AMD_SMB_STS_DONE) { udelay(500); - amd_ec_read(smbus, AMD_SMB_STS, temp + 0); + status = amd_ec_read(smbus, AMD_SMB_STS, temp + 0); + if (status) + return status; } if (~temp[0] & AMD_SMB_STS_DONE) { msleep(1); - amd_ec_read(smbus, AMD_SMB_STS, temp + 0); + status = amd_ec_read(smbus, AMD_SMB_STS, temp + 0); + if (status) + return status; } if ((~temp[0] & AMD_SMB_STS_DONE) || (temp[0] & AMD_SMB_STS_STATUS)) @@ -311,24 +363,35 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, switch (size) { case I2C_SMBUS_BYTE: case I2C_SMBUS_BYTE_DATA: - amd_ec_read(smbus, AMD_SMB_DATA, &data->byte); + status = amd_ec_read(smbus, AMD_SMB_DATA, &data->byte); + if (status) + return status; break; case I2C_SMBUS_WORD_DATA: case I2C_SMBUS_PROC_CALL: - amd_ec_read(smbus, AMD_SMB_DATA, temp + 0); - amd_ec_read(smbus, AMD_SMB_DATA + 1, temp + 1); + status = amd_ec_read(smbus, AMD_SMB_DATA, temp + 0); + if (status) + return status; + status = amd_ec_read(smbus, AMD_SMB_DATA + 1, temp + 1); + if (status) + return status; data->word = (temp[1] << 8) | temp[0]; break; case I2C_SMBUS_BLOCK_DATA: case I2C_SMBUS_BLOCK_PROC_CALL: - amd_ec_read(smbus, AMD_SMB_BCNT, &len); + status = amd_ec_read(smbus, AMD_SMB_BCNT, &len); + if (status) + return status; len = min_t(u8, len, I2C_SMBUS_BLOCK_MAX); case I2C_SMBUS_I2C_BLOCK_DATA: - for (i = 0; i < len; i++) - amd_ec_read(smbus, AMD_SMB_DATA + i, - data->block + i + 1); + for (i = 0; i < len; i++) { + status = amd_ec_read(smbus, AMD_SMB_DATA + i, + data->block + i + 1); + if (status) + return status; + } data->block[0] = len; break; } diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index c60081169cc3..02835ce7ff4b 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -3,6 +3,8 @@ Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker <mdsxyz123@yahoo.com> Copyright (C) 2007, 2008 Jean Delvare <khali@linux-fr.org> + Copyright (C) 2010 Intel Corporation, + David Woodhouse <dwmw2@infradead.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 @@ -38,11 +40,15 @@ 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 yes yes + EP80579 (Tolapai) 0x5032 32 hard yes yes yes ICH10 0x3a30 32 hard yes yes yes ICH10 0x3a60 32 hard yes yes yes - 3400/5 Series (PCH) 0x3b30 32 hard yes yes yes + 5/3400 Series (PCH) 0x3b30 32 hard yes yes yes Cougar Point (PCH) 0x1c22 32 hard yes yes yes + Patsburg (PCH) 0x1d22 32 hard yes yes yes + Patsburg (PCH) IDF 0x1d70 32 hard yes yes yes + Patsburg (PCH) IDF 0x1d71 32 hard yes yes yes + Patsburg (PCH) IDF 0x1d72 32 hard yes yes yes Features supported by this driver: Software PEC no @@ -50,12 +56,11 @@ Block buffer yes Block process call transaction no I2C block read transaction yes (doesn't use the block buffer) + Slave mode no See the file Documentation/i2c/busses/i2c-i801 for details. */ -/* Note: we assume there can only be one I801, with one SMBus interface */ - #include <linux/module.h> #include <linux/pci.h> #include <linux/kernel.h> @@ -69,16 +74,16 @@ #include <linux/dmi.h> /* I801 SMBus address offsets */ -#define SMBHSTSTS (0 + i801_smba) -#define SMBHSTCNT (2 + i801_smba) -#define SMBHSTCMD (3 + i801_smba) -#define SMBHSTADD (4 + i801_smba) -#define SMBHSTDAT0 (5 + i801_smba) -#define SMBHSTDAT1 (6 + i801_smba) -#define SMBBLKDAT (7 + i801_smba) -#define SMBPEC (8 + i801_smba) /* ICH3 and later */ -#define SMBAUXSTS (12 + i801_smba) /* ICH4 and later */ -#define SMBAUXCTL (13 + i801_smba) /* ICH4 and later */ +#define SMBHSTSTS(p) (0 + (p)->smba) +#define SMBHSTCNT(p) (2 + (p)->smba) +#define SMBHSTCMD(p) (3 + (p)->smba) +#define SMBHSTADD(p) (4 + (p)->smba) +#define SMBHSTDAT0(p) (5 + (p)->smba) +#define SMBHSTDAT1(p) (6 + (p)->smba) +#define SMBBLKDAT(p) (7 + (p)->smba) +#define SMBPEC(p) (8 + (p)->smba) /* ICH3 and later */ +#define SMBAUXSTS(p) (12 + (p)->smba) /* ICH4 and later */ +#define SMBAUXCTL(p) (13 + (p)->smba) /* ICH4 and later */ /* PCI Address Constants */ #define SMBBAR 4 @@ -127,16 +132,25 @@ SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR | \ SMBHSTSTS_INTR) -static unsigned long i801_smba; -static unsigned char i801_original_hstcfg; +/* Patsburg also has three 'Integrated Device Function' SMBus controllers */ +#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0 0x1d70 +#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1 0x1d71 +#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2 0x1d72 + +struct i801_priv { + struct i2c_adapter adapter; + unsigned long smba; + unsigned char original_hstcfg; + struct pci_dev *pci_dev; + unsigned int features; +}; + static struct pci_driver i801_driver; -static struct pci_dev *I801_dev; #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 const char *i801_feature_names[] = { "SMBus PEC", @@ -151,24 +165,24 @@ MODULE_PARM_DESC(disable_features, "Disable selected driver features"); /* Make sure the SMBus host is ready to start transmitting. Return 0 if it is, -EBUSY if it is not. */ -static int i801_check_pre(void) +static int i801_check_pre(struct i801_priv *priv) { int status; - status = inb_p(SMBHSTSTS); + status = inb_p(SMBHSTSTS(priv)); if (status & SMBHSTSTS_HOST_BUSY) { - dev_err(&I801_dev->dev, "SMBus is busy, can't use it!\n"); + dev_err(&priv->pci_dev->dev, "SMBus is busy, can't use it!\n"); return -EBUSY; } status &= STATUS_FLAGS; if (status) { - dev_dbg(&I801_dev->dev, "Clearing status flags (%02x)\n", + dev_dbg(&priv->pci_dev->dev, "Clearing status flags (%02x)\n", status); - outb_p(status, SMBHSTSTS); - status = inb_p(SMBHSTSTS) & STATUS_FLAGS; + outb_p(status, SMBHSTSTS(priv)); + status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS; if (status) { - dev_err(&I801_dev->dev, + dev_err(&priv->pci_dev->dev, "Failed clearing status flags (%02x)\n", status); return -EBUSY; @@ -179,48 +193,50 @@ static int i801_check_pre(void) } /* Convert the status register to an error code, and clear it. */ -static int i801_check_post(int status, int timeout) +static int i801_check_post(struct i801_priv *priv, int status, int timeout) { int result = 0; /* If the SMBus is still busy, we give up */ if (timeout) { - dev_err(&I801_dev->dev, "Transaction timeout\n"); + dev_err(&priv->pci_dev->dev, "Transaction timeout\n"); /* try to stop the current command */ - dev_dbg(&I801_dev->dev, "Terminating the current operation\n"); - outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT); + dev_dbg(&priv->pci_dev->dev, "Terminating the current operation\n"); + outb_p(inb_p(SMBHSTCNT(priv)) | SMBHSTCNT_KILL, + SMBHSTCNT(priv)); msleep(1); - outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), SMBHSTCNT); + outb_p(inb_p(SMBHSTCNT(priv)) & (~SMBHSTCNT_KILL), + SMBHSTCNT(priv)); /* Check if it worked */ - status = inb_p(SMBHSTSTS); + status = inb_p(SMBHSTSTS(priv)); if ((status & SMBHSTSTS_HOST_BUSY) || !(status & SMBHSTSTS_FAILED)) - dev_err(&I801_dev->dev, + dev_err(&priv->pci_dev->dev, "Failed terminating the transaction\n"); - outb_p(STATUS_FLAGS, SMBHSTSTS); + outb_p(STATUS_FLAGS, SMBHSTSTS(priv)); return -ETIMEDOUT; } if (status & SMBHSTSTS_FAILED) { result = -EIO; - dev_err(&I801_dev->dev, "Transaction failed\n"); + dev_err(&priv->pci_dev->dev, "Transaction failed\n"); } if (status & SMBHSTSTS_DEV_ERR) { result = -ENXIO; - dev_dbg(&I801_dev->dev, "No response\n"); + dev_dbg(&priv->pci_dev->dev, "No response\n"); } if (status & SMBHSTSTS_BUS_ERR) { result = -EAGAIN; - dev_dbg(&I801_dev->dev, "Lost arbitration\n"); + dev_dbg(&priv->pci_dev->dev, "Lost arbitration\n"); } if (result) { /* Clear error flags */ - outb_p(status & STATUS_FLAGS, SMBHSTSTS); - status = inb_p(SMBHSTSTS) & STATUS_FLAGS; + outb_p(status & STATUS_FLAGS, SMBHSTSTS(priv)); + status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS; if (status) { - dev_warn(&I801_dev->dev, "Failed clearing status " + dev_warn(&priv->pci_dev->dev, "Failed clearing status " "flags at end of transaction (%02x)\n", status); } @@ -229,86 +245,88 @@ static int i801_check_post(int status, int timeout) return result; } -static int i801_transaction(int xact) +static int i801_transaction(struct i801_priv *priv, int xact) { int status; int result; int timeout = 0; - result = i801_check_pre(); + result = i801_check_pre(priv); if (result < 0) return result; /* the current contents of SMBHSTCNT can be overwritten, since PEC, * INTREN, SMBSCMD are passed in xact */ - outb_p(xact | I801_START, SMBHSTCNT); + outb_p(xact | I801_START, SMBHSTCNT(priv)); /* We will always wait for a fraction of a second! */ do { msleep(1); - status = inb_p(SMBHSTSTS); + status = inb_p(SMBHSTSTS(priv)); } while ((status & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT)); - result = i801_check_post(status, timeout > MAX_TIMEOUT); + result = i801_check_post(priv, status, timeout > MAX_TIMEOUT); if (result < 0) return result; - outb_p(SMBHSTSTS_INTR, SMBHSTSTS); + outb_p(SMBHSTSTS_INTR, SMBHSTSTS(priv)); return 0; } /* wait for INTR bit as advised by Intel */ -static void i801_wait_hwpec(void) +static void i801_wait_hwpec(struct i801_priv *priv) { int timeout = 0; int status; do { msleep(1); - status = inb_p(SMBHSTSTS); + status = inb_p(SMBHSTSTS(priv)); } while ((!(status & SMBHSTSTS_INTR)) && (timeout++ < MAX_TIMEOUT)); if (timeout > MAX_TIMEOUT) - dev_dbg(&I801_dev->dev, "PEC Timeout!\n"); + dev_dbg(&priv->pci_dev->dev, "PEC Timeout!\n"); - outb_p(status, SMBHSTSTS); + outb_p(status, SMBHSTSTS(priv)); } -static int i801_block_transaction_by_block(union i2c_smbus_data *data, +static int i801_block_transaction_by_block(struct i801_priv *priv, + union i2c_smbus_data *data, char read_write, int hwpec) { int i, len; int status; - inb_p(SMBHSTCNT); /* reset the data buffer index */ + inb_p(SMBHSTCNT(priv)); /* reset the data buffer index */ /* Use 32-byte buffer to process this transaction */ if (read_write == I2C_SMBUS_WRITE) { len = data->block[0]; - outb_p(len, SMBHSTDAT0); + outb_p(len, SMBHSTDAT0(priv)); for (i = 0; i < len; i++) - outb_p(data->block[i+1], SMBBLKDAT); + outb_p(data->block[i+1], SMBBLKDAT(priv)); } - status = i801_transaction(I801_BLOCK_DATA | ENABLE_INT9 | + status = i801_transaction(priv, I801_BLOCK_DATA | ENABLE_INT9 | I801_PEC_EN * hwpec); if (status) return status; if (read_write == I2C_SMBUS_READ) { - len = inb_p(SMBHSTDAT0); + len = inb_p(SMBHSTDAT0(priv)); if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) return -EPROTO; data->block[0] = len; for (i = 0; i < len; i++) - data->block[i + 1] = inb_p(SMBBLKDAT); + data->block[i + 1] = inb_p(SMBBLKDAT(priv)); } return 0; } -static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data, +static int i801_block_transaction_byte_by_byte(struct i801_priv *priv, + union i2c_smbus_data *data, char read_write, int command, int hwpec) { @@ -318,15 +336,15 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data, int result; int timeout; - result = i801_check_pre(); + result = i801_check_pre(priv); if (result < 0) return result; len = data->block[0]; if (read_write == I2C_SMBUS_WRITE) { - outb_p(len, SMBHSTDAT0); - outb_p(data->block[1], SMBBLKDAT); + outb_p(len, SMBHSTDAT0(priv)); + outb_p(data->block[1], SMBBLKDAT(priv)); } for (i = 1; i <= len; i++) { @@ -342,34 +360,37 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data, else smbcmd = I801_BLOCK_DATA; } - outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT); + outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT(priv)); if (i == 1) - outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT); + outb_p(inb(SMBHSTCNT(priv)) | I801_START, + SMBHSTCNT(priv)); /* We will always wait for a fraction of a second! */ timeout = 0; do { msleep(1); - status = inb_p(SMBHSTSTS); + status = inb_p(SMBHSTSTS(priv)); } while ((!(status & SMBHSTSTS_BYTE_DONE)) && (timeout++ < MAX_TIMEOUT)); - result = i801_check_post(status, timeout > MAX_TIMEOUT); + result = i801_check_post(priv, status, timeout > MAX_TIMEOUT); if (result < 0) return result; if (i == 1 && read_write == I2C_SMBUS_READ && command != I2C_SMBUS_I2C_BLOCK_DATA) { - len = inb_p(SMBHSTDAT0); + len = inb_p(SMBHSTDAT0(priv)); if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) { - dev_err(&I801_dev->dev, + dev_err(&priv->pci_dev->dev, "Illegal SMBus block read size %d\n", len); /* Recover */ - while (inb_p(SMBHSTSTS) & SMBHSTSTS_HOST_BUSY) - outb_p(SMBHSTSTS_BYTE_DONE, SMBHSTSTS); - outb_p(SMBHSTSTS_INTR, SMBHSTSTS); + while (inb_p(SMBHSTSTS(priv)) & + SMBHSTSTS_HOST_BUSY) + outb_p(SMBHSTSTS_BYTE_DONE, + SMBHSTSTS(priv)); + outb_p(SMBHSTSTS_INTR, SMBHSTSTS(priv)); return -EPROTO; } data->block[0] = len; @@ -377,27 +398,28 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data, /* Retrieve/store value in SMBBLKDAT */ if (read_write == I2C_SMBUS_READ) - data->block[i] = inb_p(SMBBLKDAT); + data->block[i] = inb_p(SMBBLKDAT(priv)); if (read_write == I2C_SMBUS_WRITE && i+1 <= len) - outb_p(data->block[i+1], SMBBLKDAT); + outb_p(data->block[i+1], SMBBLKDAT(priv)); /* signals SMBBLKDAT ready */ - outb_p(SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR, SMBHSTSTS); + outb_p(SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR, SMBHSTSTS(priv)); } return 0; } -static int i801_set_block_buffer_mode(void) +static int i801_set_block_buffer_mode(struct i801_priv *priv) { - outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_E32B, SMBAUXCTL); - if ((inb_p(SMBAUXCTL) & SMBAUXCTL_E32B) == 0) + outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_E32B, SMBAUXCTL(priv)); + if ((inb_p(SMBAUXCTL(priv)) & SMBAUXCTL_E32B) == 0) return -EIO; return 0; } /* Block transaction function */ -static int i801_block_transaction(union i2c_smbus_data *data, char read_write, +static int i801_block_transaction(struct i801_priv *priv, + union i2c_smbus_data *data, char read_write, int command, int hwpec) { int result = 0; @@ -406,11 +428,11 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, if (command == I2C_SMBUS_I2C_BLOCK_DATA) { if (read_write == I2C_SMBUS_WRITE) { /* set I2C_EN bit in configuration register */ - pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc); - pci_write_config_byte(I801_dev, SMBHSTCFG, + pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &hostc); + pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc | SMBHSTCFG_I2C_EN); - } else if (!(i801_features & FEATURE_I2C_BLOCK_READ)) { - dev_err(&I801_dev->dev, + } else if (!(priv->features & FEATURE_I2C_BLOCK_READ)) { + dev_err(&priv->pci_dev->dev, "I2C block read is unsupported!\n"); return -EOPNOTSUPP; } @@ -429,22 +451,23 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, /* Experience has shown that the block buffer can only be used for SMBus (not I2C) block transactions, even though the datasheet doesn't mention this limitation. */ - if ((i801_features & FEATURE_BLOCK_BUFFER) + if ((priv->features & FEATURE_BLOCK_BUFFER) && command != I2C_SMBUS_I2C_BLOCK_DATA - && i801_set_block_buffer_mode() == 0) - result = i801_block_transaction_by_block(data, read_write, - hwpec); + && i801_set_block_buffer_mode(priv) == 0) + result = i801_block_transaction_by_block(priv, data, + read_write, hwpec); else - result = i801_block_transaction_byte_by_byte(data, read_write, + result = i801_block_transaction_byte_by_byte(priv, data, + read_write, command, hwpec); if (result == 0 && hwpec) - i801_wait_hwpec(); + i801_wait_hwpec(priv); 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); + pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc); } return result; } @@ -457,81 +480,85 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, int hwpec; int block = 0; int ret, xact = 0; + struct i801_priv *priv = i2c_get_adapdata(adap); - hwpec = (i801_features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC) + hwpec = (priv->features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK && size != I2C_SMBUS_I2C_BLOCK_DATA; switch (size) { case I2C_SMBUS_QUICK: outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); + SMBHSTADD(priv)); xact = I801_QUICK; break; case I2C_SMBUS_BYTE: outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); + SMBHSTADD(priv)); if (read_write == I2C_SMBUS_WRITE) - outb_p(command, SMBHSTCMD); + outb_p(command, SMBHSTCMD(priv)); xact = I801_BYTE; break; case I2C_SMBUS_BYTE_DATA: outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - outb_p(command, SMBHSTCMD); + SMBHSTADD(priv)); + outb_p(command, SMBHSTCMD(priv)); if (read_write == I2C_SMBUS_WRITE) - outb_p(data->byte, SMBHSTDAT0); + outb_p(data->byte, SMBHSTDAT0(priv)); xact = I801_BYTE_DATA; break; case I2C_SMBUS_WORD_DATA: outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - outb_p(command, SMBHSTCMD); + SMBHSTADD(priv)); + outb_p(command, SMBHSTCMD(priv)); if (read_write == I2C_SMBUS_WRITE) { - outb_p(data->word & 0xff, SMBHSTDAT0); - outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); + outb_p(data->word & 0xff, SMBHSTDAT0(priv)); + outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1(priv)); } xact = I801_WORD_DATA; break; case I2C_SMBUS_BLOCK_DATA: outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - outb_p(command, SMBHSTCMD); + SMBHSTADD(priv)); + outb_p(command, SMBHSTCMD(priv)); 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); + outb_p((addr & 0x7f) << 1, SMBHSTADD(priv)); 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); + outb_p(command, SMBHSTDAT1(priv)); } else - outb_p(command, SMBHSTCMD); + outb_p(command, SMBHSTCMD(priv)); block = 1; break; default: - dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size); + dev_err(&priv->pci_dev->dev, "Unsupported transaction %d\n", + size); return -EOPNOTSUPP; } if (hwpec) /* enable/disable hardware PEC */ - outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_CRC, SMBAUXCTL); + outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_CRC, SMBAUXCTL(priv)); else - outb_p(inb_p(SMBAUXCTL) & (~SMBAUXCTL_CRC), SMBAUXCTL); + outb_p(inb_p(SMBAUXCTL(priv)) & (~SMBAUXCTL_CRC), + SMBAUXCTL(priv)); if (block) - ret = i801_block_transaction(data, read_write, size, hwpec); + ret = i801_block_transaction(priv, data, read_write, size, + hwpec); else - ret = i801_transaction(xact | ENABLE_INT9); + ret = i801_transaction(priv, xact | ENABLE_INT9); /* 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 || block) - outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), - SMBAUXCTL); + outb_p(inb_p(SMBAUXCTL(priv)) & + ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv)); if (block) return ret; @@ -543,10 +570,11 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, switch (xact & 0x7f) { case I801_BYTE: /* Result put in SMBHSTDAT0 */ case I801_BYTE_DATA: - data->byte = inb_p(SMBHSTDAT0); + data->byte = inb_p(SMBHSTDAT0(priv)); break; case I801_WORD_DATA: - data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); + data->word = inb_p(SMBHSTDAT0(priv)) + + (inb_p(SMBHSTDAT1(priv)) << 8); break; } return 0; @@ -555,11 +583,13 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, static u32 i801_func(struct i2c_adapter *adapter) { + struct i801_priv *priv = i2c_get_adapdata(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 | - ((i801_features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0) | - ((i801_features & FEATURE_I2C_BLOCK_READ) ? + ((priv->features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0) | + ((priv->features & FEATURE_I2C_BLOCK_READ) ? I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0); } @@ -568,12 +598,6 @@ static const struct i2c_algorithm smbus_algorithm = { .functionality = i801_func, }; -static struct i2c_adapter i801_adapter = { - .owner = THIS_MODULE, - .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, - .algo = &smbus_algorithm, -}; - static const struct pci_device_id i801_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) }, @@ -587,11 +611,15 @@ static const struct pci_device_id i801_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_6) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TOLAPAI_1) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EP80579_1) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_4) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_5) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PCH_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CPT_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2) }, { 0, } }; @@ -704,16 +732,25 @@ static int __devinit i801_probe(struct pci_dev *dev, { unsigned char temp; int err, i; + struct i801_priv *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + i2c_set_adapdata(&priv->adapter, priv); + priv->adapter.owner = THIS_MODULE; + priv->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; + priv->adapter.algo = &smbus_algorithm; - I801_dev = dev; - i801_features = 0; + priv->pci_dev = dev; switch (dev->device) { default: - i801_features |= FEATURE_I2C_BLOCK_READ; + priv->features |= FEATURE_I2C_BLOCK_READ; /* fall through */ case PCI_DEVICE_ID_INTEL_82801DB_3: - i801_features |= FEATURE_SMBUS_PEC; - i801_features |= FEATURE_BLOCK_BUFFER; + priv->features |= FEATURE_SMBUS_PEC; + priv->features |= FEATURE_BLOCK_BUFFER; /* fall through */ case PCI_DEVICE_ID_INTEL_82801CA_3: case PCI_DEVICE_ID_INTEL_82801BA_2: @@ -724,11 +761,11 @@ static int __devinit i801_probe(struct pci_dev *dev, /* Disable features on user request */ for (i = 0; i < ARRAY_SIZE(i801_feature_names); i++) { - if (i801_features & disable_features & (1 << i)) + if (priv->features & disable_features & (1 << i)) dev_notice(&dev->dev, "%s disabled by user\n", i801_feature_names[i]); } - i801_features &= ~disable_features; + priv->features &= ~disable_features; err = pci_enable_device(dev); if (err) { @@ -738,8 +775,8 @@ static int __devinit i801_probe(struct pci_dev *dev, } /* Determine the address of the SMBus area */ - i801_smba = pci_resource_start(dev, SMBBAR); - if (!i801_smba) { + priv->smba = pci_resource_start(dev, SMBBAR); + if (!priv->smba) { dev_err(&dev->dev, "SMBus base address uninitialized, " "upgrade BIOS\n"); err = -ENODEV; @@ -755,19 +792,19 @@ static int __devinit i801_probe(struct pci_dev *dev, err = pci_request_region(dev, SMBBAR, i801_driver.name); if (err) { dev_err(&dev->dev, "Failed to request SMBus region " - "0x%lx-0x%Lx\n", i801_smba, + "0x%lx-0x%Lx\n", priv->smba, (unsigned long long)pci_resource_end(dev, SMBBAR)); goto exit; } - pci_read_config_byte(I801_dev, SMBHSTCFG, &temp); - i801_original_hstcfg = temp; + pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &temp); + priv->original_hstcfg = temp; temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */ if (!(temp & SMBHSTCFG_HST_EN)) { dev_info(&dev->dev, "Enabling SMBus device\n"); temp |= SMBHSTCFG_HST_EN; } - pci_write_config_byte(I801_dev, SMBHSTCFG, temp); + pci_write_config_byte(priv->pci_dev, SMBHSTCFG, temp); if (temp & SMBHSTCFG_SMB_SMI_EN) dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n"); @@ -775,19 +812,19 @@ static int __devinit i801_probe(struct pci_dev *dev, 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); + if (priv->features & (FEATURE_SMBUS_PEC | FEATURE_BLOCK_BUFFER)) + outb_p(inb_p(SMBAUXCTL(priv)) & + ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv)); /* set up the sysfs linkage to our parent device */ - i801_adapter.dev.parent = &dev->dev; + priv->adapter.dev.parent = &dev->dev; /* Retry up to 3 times on lost arbitration */ - i801_adapter.retries = 3; + priv->adapter.retries = 3; - snprintf(i801_adapter.name, sizeof(i801_adapter.name), - "SMBus I801 adapter at %04lx", i801_smba); - err = i2c_add_adapter(&i801_adapter); + snprintf(priv->adapter.name, sizeof(priv->adapter.name), + "SMBus I801 adapter at %04lx", priv->smba); + err = i2c_add_adapter(&priv->adapter); if (err) { dev_err(&dev->dev, "Failed to add SMBus adapter\n"); goto exit_release; @@ -801,27 +838,33 @@ static int __devinit i801_probe(struct pci_dev *dev, memset(&info, 0, sizeof(struct i2c_board_info)); info.addr = apanel_addr; strlcpy(info.type, "fujitsu_apanel", I2C_NAME_SIZE); - i2c_new_device(&i801_adapter, &info); + i2c_new_device(&priv->adapter, &info); } #endif #if defined CONFIG_SENSORS_FSCHMD || defined CONFIG_SENSORS_FSCHMD_MODULE if (dmi_name_in_vendors("FUJITSU")) - dmi_walk(dmi_check_onboard_devices, &i801_adapter); + dmi_walk(dmi_check_onboard_devices, &priv->adapter); #endif + pci_set_drvdata(dev, priv); return 0; exit_release: pci_release_region(dev, SMBBAR); exit: + kfree(priv); return err; } static void __devexit i801_remove(struct pci_dev *dev) { - i2c_del_adapter(&i801_adapter); - pci_write_config_byte(I801_dev, SMBHSTCFG, i801_original_hstcfg); + struct i801_priv *priv = pci_get_drvdata(dev); + + i2c_del_adapter(&priv->adapter); + pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg); pci_release_region(dev, SMBBAR); + pci_set_drvdata(dev, NULL); + kfree(priv); /* * do not call pci_disable_device(dev) since it can cause hard hangs on * some systems during power-off (eg. Fujitsu-Siemens Lifebook E8010) @@ -831,8 +874,10 @@ static void __devexit i801_remove(struct pci_dev *dev) #ifdef CONFIG_PM static int i801_suspend(struct pci_dev *dev, pm_message_t mesg) { + struct i801_priv *priv = pci_get_drvdata(dev); + pci_save_state(dev); - pci_write_config_byte(dev, SMBHSTCFG, i801_original_hstcfg); + pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg); pci_set_power_state(dev, pci_choose_state(dev, mesg)); return 0; } diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index 89eedf45d30e..6e3c38240336 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -41,7 +41,6 @@ #include <asm/irq.h> #include <linux/io.h> #include <linux/i2c.h> -#include <linux/i2c-id.h> #include <linux/of_platform.h> #include <linux/of_i2c.h> diff --git a/drivers/i2c/busses/i2c-intel-mid.c b/drivers/i2c/busses/i2c-intel-mid.c new file mode 100644 index 000000000000..80f70d3a744d --- /dev/null +++ b/drivers/i2c/busses/i2c-intel-mid.c @@ -0,0 +1,1135 @@ +/* + * Support for Moorestown/Medfield I2C chip + * + * Copyright (c) 2009 Intel Corporation. + * Copyright (c) 2009 Synopsys. Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, version + * 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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., 51 + * Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/err.h> +#include <linux/slab.h> +#include <linux/stat.h> +#include <linux/delay.h> +#include <linux/i2c.h> +#include <linux/init.h> +#include <linux/pci.h> +#include <linux/interrupt.h> +#include <linux/pm_runtime.h> +#include <linux/io.h> + +#define DRIVER_NAME "i2c-intel-mid" +#define VERSION "Version 0.5ac2" +#define PLATFORM "Moorestown/Medfield" + +/* Tables use: 0 Moorestown, 1 Medfield */ +#define NUM_PLATFORMS 2 +enum platform_enum { + MOORESTOWN = 0, + MEDFIELD = 1, +}; + +enum mid_i2c_status { + STATUS_IDLE = 0, + STATUS_READ_START, + STATUS_READ_IN_PROGRESS, + STATUS_READ_SUCCESS, + STATUS_WRITE_START, + STATUS_WRITE_SUCCESS, + STATUS_XFER_ABORT, + STATUS_STANDBY +}; + +/** + * struct intel_mid_i2c_private - per device I²C context + * @adap: core i2c layer adapter information + * @dev: device reference for power management + * @base: register base + * @speed: speed mode for this port + * @complete: completion object for transaction wait + * @abort: reason for last abort + * @rx_buf: pointer into working receive buffer + * @rx_buf_len: receive buffer length + * @status: adapter state machine + * @msg: the message we are currently processing + * @platform: the MID device type we are part of + * @lock: transaction serialization + * + * We allocate one of these per device we discover, it holds the core + * i2c layer objects and the data we need to track privately. + */ +struct intel_mid_i2c_private { + struct i2c_adapter adap; + struct device *dev; + void __iomem *base; + int speed; + struct completion complete; + int abort; + u8 *rx_buf; + int rx_buf_len; + enum mid_i2c_status status; + struct i2c_msg *msg; + enum platform_enum platform; + struct mutex lock; +}; + +#define NUM_SPEEDS 3 + +#define ACTIVE 0 +#define STANDBY 1 + + +/* Control register */ +#define IC_CON 0x00 +#define SLV_DIS (1 << 6) /* Disable slave mode */ +#define RESTART (1 << 5) /* Send a Restart condition */ +#define ADDR_10BIT (1 << 4) /* 10-bit addressing */ +#define STANDARD_MODE (1 << 1) /* standard mode */ +#define FAST_MODE (2 << 1) /* fast mode */ +#define HIGH_MODE (3 << 1) /* high speed mode */ +#define MASTER_EN (1 << 0) /* Master mode */ + +/* Target address register */ +#define IC_TAR 0x04 +#define IC_TAR_10BIT_ADDR (1 << 12) /* 10-bit addressing */ +#define IC_TAR_SPECIAL (1 << 11) /* Perform special I2C cmd */ +#define IC_TAR_GC_OR_START (1 << 10) /* 0: Gerneral Call Address */ + /* 1: START BYTE */ +/* Slave Address Register */ +#define IC_SAR 0x08 /* Not used in Master mode */ + +/* High Speed Master Mode Code Address Register */ +#define IC_HS_MADDR 0x0c + +/* Rx/Tx Data Buffer and Command Register */ +#define IC_DATA_CMD 0x10 +#define IC_RD (1 << 8) /* 1: Read 0: Write */ + +/* Standard Speed Clock SCL High Count Register */ +#define IC_SS_SCL_HCNT 0x14 + +/* Standard Speed Clock SCL Low Count Register */ +#define IC_SS_SCL_LCNT 0x18 + +/* Fast Speed Clock SCL High Count Register */ +#define IC_FS_SCL_HCNT 0x1c + +/* Fast Spedd Clock SCL Low Count Register */ +#define IC_FS_SCL_LCNT 0x20 + +/* High Speed Clock SCL High Count Register */ +#define IC_HS_SCL_HCNT 0x24 + +/* High Speed Clock SCL Low Count Register */ +#define IC_HS_SCL_LCNT 0x28 + +/* Interrupt Status Register */ +#define IC_INTR_STAT 0x2c /* Read only */ +#define R_GEN_CALL (1 << 11) +#define R_START_DET (1 << 10) +#define R_STOP_DET (1 << 9) +#define R_ACTIVITY (1 << 8) +#define R_RX_DONE (1 << 7) +#define R_TX_ABRT (1 << 6) +#define R_RD_REQ (1 << 5) +#define R_TX_EMPTY (1 << 4) +#define R_TX_OVER (1 << 3) +#define R_RX_FULL (1 << 2) +#define R_RX_OVER (1 << 1) +#define R_RX_UNDER (1 << 0) + +/* Interrupt Mask Register */ +#define IC_INTR_MASK 0x30 /* Read and Write */ +#define M_GEN_CALL (1 << 11) +#define M_START_DET (1 << 10) +#define M_STOP_DET (1 << 9) +#define M_ACTIVITY (1 << 8) +#define M_RX_DONE (1 << 7) +#define M_TX_ABRT (1 << 6) +#define M_RD_REQ (1 << 5) +#define M_TX_EMPTY (1 << 4) +#define M_TX_OVER (1 << 3) +#define M_RX_FULL (1 << 2) +#define M_RX_OVER (1 << 1) +#define M_RX_UNDER (1 << 0) + +/* Raw Interrupt Status Register */ +#define IC_RAW_INTR_STAT 0x34 /* Read Only */ +#define GEN_CALL (1 << 11) /* General call */ +#define START_DET (1 << 10) /* (RE)START occured */ +#define STOP_DET (1 << 9) /* STOP occured */ +#define ACTIVITY (1 << 8) /* Bus busy */ +#define RX_DONE (1 << 7) /* Not used in Master mode */ +#define TX_ABRT (1 << 6) /* Transmit Abort */ +#define RD_REQ (1 << 5) /* Not used in Master mode */ +#define TX_EMPTY (1 << 4) /* TX FIFO <= threshold */ +#define TX_OVER (1 << 3) /* TX FIFO overflow */ +#define RX_FULL (1 << 2) /* RX FIFO >= threshold */ +#define RX_OVER (1 << 1) /* RX FIFO overflow */ +#define RX_UNDER (1 << 0) /* RX FIFO empty */ + +/* Receive FIFO Threshold Register */ +#define IC_RX_TL 0x38 + +/* Transmit FIFO Treshold Register */ +#define IC_TX_TL 0x3c + +/* Clear Combined and Individual Interrupt Register */ +#define IC_CLR_INTR 0x40 +#define CLR_INTR (1 << 0) + +/* Clear RX_UNDER Interrupt Register */ +#define IC_CLR_RX_UNDER 0x44 +#define CLR_RX_UNDER (1 << 0) + +/* Clear RX_OVER Interrupt Register */ +#define IC_CLR_RX_OVER 0x48 +#define CLR_RX_OVER (1 << 0) + +/* Clear TX_OVER Interrupt Register */ +#define IC_CLR_TX_OVER 0x4c +#define CLR_TX_OVER (1 << 0) + +#define IC_CLR_RD_REQ 0x50 + +/* Clear TX_ABRT Interrupt Register */ +#define IC_CLR_TX_ABRT 0x54 +#define CLR_TX_ABRT (1 << 0) +#define IC_CLR_RX_DONE 0x58 + +/* Clear ACTIVITY Interrupt Register */ +#define IC_CLR_ACTIVITY 0x5c +#define CLR_ACTIVITY (1 << 0) + +/* Clear STOP_DET Interrupt Register */ +#define IC_CLR_STOP_DET 0x60 +#define CLR_STOP_DET (1 << 0) + +/* Clear START_DET Interrupt Register */ +#define IC_CLR_START_DET 0x64 +#define CLR_START_DET (1 << 0) + +/* Clear GEN_CALL Interrupt Register */ +#define IC_CLR_GEN_CALL 0x68 +#define CLR_GEN_CALL (1 << 0) + +/* Enable Register */ +#define IC_ENABLE 0x6c +#define ENABLE (1 << 0) + +/* Status Register */ +#define IC_STATUS 0x70 /* Read Only */ +#define STAT_SLV_ACTIVITY (1 << 6) /* Slave not in idle */ +#define STAT_MST_ACTIVITY (1 << 5) /* Master not in idle */ +#define STAT_RFF (1 << 4) /* RX FIFO Full */ +#define STAT_RFNE (1 << 3) /* RX FIFO Not Empty */ +#define STAT_TFE (1 << 2) /* TX FIFO Empty */ +#define STAT_TFNF (1 << 1) /* TX FIFO Not Full */ +#define STAT_ACTIVITY (1 << 0) /* Activity Status */ + +/* Transmit FIFO Level Register */ +#define IC_TXFLR 0x74 /* Read Only */ +#define TXFLR (1 << 0) /* TX FIFO level */ + +/* Receive FIFO Level Register */ +#define IC_RXFLR 0x78 /* Read Only */ +#define RXFLR (1 << 0) /* RX FIFO level */ + +/* Transmit Abort Source Register */ +#define IC_TX_ABRT_SOURCE 0x80 +#define ABRT_SLVRD_INTX (1 << 15) +#define ABRT_SLV_ARBLOST (1 << 14) +#define ABRT_SLVFLUSH_TXFIFO (1 << 13) +#define ARB_LOST (1 << 12) +#define ABRT_MASTER_DIS (1 << 11) +#define ABRT_10B_RD_NORSTRT (1 << 10) +#define ABRT_SBYTE_NORSTRT (1 << 9) +#define ABRT_HS_NORSTRT (1 << 8) +#define ABRT_SBYTE_ACKDET (1 << 7) +#define ABRT_HS_ACKDET (1 << 6) +#define ABRT_GCALL_READ (1 << 5) +#define ABRT_GCALL_NOACK (1 << 4) +#define ABRT_TXDATA_NOACK (1 << 3) +#define ABRT_10ADDR2_NOACK (1 << 2) +#define ABRT_10ADDR1_NOACK (1 << 1) +#define ABRT_7B_ADDR_NOACK (1 << 0) + +/* Enable Status Register */ +#define IC_ENABLE_STATUS 0x9c +#define IC_EN (1 << 0) /* I2C in an enabled state */ + +/* Component Parameter Register 1*/ +#define IC_COMP_PARAM_1 0xf4 +#define APB_DATA_WIDTH (0x3 << 0) + +/* added by xiaolin --begin */ +#define SS_MIN_SCL_HIGH 4000 +#define SS_MIN_SCL_LOW 4700 +#define FS_MIN_SCL_HIGH 600 +#define FS_MIN_SCL_LOW 1300 +#define HS_MIN_SCL_HIGH_100PF 60 +#define HS_MIN_SCL_LOW_100PF 120 + +#define STANDARD 0 +#define FAST 1 +#define HIGH 2 + +#define NUM_SPEEDS 3 + +static int speed_mode[6] = { + FAST, + FAST, + FAST, + STANDARD, + FAST, + FAST +}; + +static int ctl_num = 6; +module_param_array(speed_mode, int, &ctl_num, S_IRUGO); +MODULE_PARM_DESC(speed_mode, "Set the speed of the i2c interface (0-2)"); + +/** + * intel_mid_i2c_disable - Disable I2C controller + * @adap: struct pointer to i2c_adapter + * + * Return Value: + * 0 success + * -EBUSY if device is busy + * -ETIMEDOUT if i2c cannot be disabled within the given time + * + * I2C bus state should be checked prior to disabling the hardware. If bus is + * not in idle state, an errno is returned. Write "0" to IC_ENABLE to disable + * I2C controller. + */ +static int intel_mid_i2c_disable(struct i2c_adapter *adap) +{ + struct intel_mid_i2c_private *i2c = i2c_get_adapdata(adap); + int err = 0; + int count = 0; + int ret1, ret2; + static const u16 delay[NUM_SPEEDS] = {100, 25, 3}; + + /* Set IC_ENABLE to 0 */ + writel(0, i2c->base + IC_ENABLE); + + /* Check if device is busy */ + dev_dbg(&adap->dev, "mrst i2c disable\n"); + while ((ret1 = readl(i2c->base + IC_ENABLE_STATUS) & 0x1) + || (ret2 = readl(i2c->base + IC_STATUS) & 0x1)) { + udelay(delay[i2c->speed]); + writel(0, i2c->base + IC_ENABLE); + dev_dbg(&adap->dev, "i2c is busy, count is %d speed %d\n", + count, i2c->speed); + if (count++ > 10) { + err = -ETIMEDOUT; + break; + } + } + + /* Clear all interrupts */ + readl(i2c->base + IC_CLR_INTR); + readl(i2c->base + IC_CLR_STOP_DET); + readl(i2c->base + IC_CLR_START_DET); + readl(i2c->base + IC_CLR_ACTIVITY); + readl(i2c->base + IC_CLR_TX_ABRT); + readl(i2c->base + IC_CLR_RX_OVER); + readl(i2c->base + IC_CLR_RX_UNDER); + readl(i2c->base + IC_CLR_TX_OVER); + readl(i2c->base + IC_CLR_RX_DONE); + readl(i2c->base + IC_CLR_GEN_CALL); + + /* Disable all interupts */ + writel(0x0000, i2c->base + IC_INTR_MASK); + + return err; +} + +/** + * intel_mid_i2c_hwinit - Initialize the I2C hardware registers + * @dev: pci device struct pointer + * + * This function will be called in intel_mid_i2c_probe() before device + * registration. + * + * Return Values: + * 0 success + * -EBUSY i2c cannot be disabled + * -ETIMEDOUT i2c cannot be disabled + * -EFAULT If APB data width is not 32-bit wide + * + * I2C should be disabled prior to other register operation. If failed, an + * errno is returned. Mask and Clear all interrpts, this should be done at + * first. Set common registers which will not be modified during normal + * transfers, including: controll register, FIFO threshold and clock freq. + * Check APB data width at last. + */ +static int intel_mid_i2c_hwinit(struct intel_mid_i2c_private *i2c) +{ + int err; + + static const u16 hcnt[NUM_PLATFORMS][NUM_SPEEDS] = { + { 0x75, 0x15, 0x07 }, + { 0x04c, 0x10, 0x06 } + }; + static const u16 lcnt[NUM_PLATFORMS][NUM_SPEEDS] = { + { 0x7C, 0x21, 0x0E }, + { 0x053, 0x19, 0x0F } + }; + + /* Disable i2c first */ + err = intel_mid_i2c_disable(&i2c->adap); + if (err) + return err; + + /* + * Setup clock frequency and speed mode + * Enable restart condition, + * enable master FSM, disable slave FSM, + * use target address when initiating transfer + */ + + writel((i2c->speed + 1) << 1 | SLV_DIS | RESTART | MASTER_EN, + i2c->base + IC_CON); + writel(hcnt[i2c->platform][i2c->speed], + i2c->base + (IC_SS_SCL_HCNT + (i2c->speed << 3))); + writel(lcnt[i2c->platform][i2c->speed], + i2c->base + (IC_SS_SCL_LCNT + (i2c->speed << 3))); + + /* Set tranmit & receive FIFO threshold to zero */ + writel(0x0, i2c->base + IC_RX_TL); + writel(0x0, i2c->base + IC_TX_TL); + + return 0; +} + +/** + * intel_mid_i2c_func - Return the supported three I2C operations. + * @adapter: i2c_adapter struct pointer + */ +static u32 intel_mid_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SMBUS_EMUL; +} + +/** + * intel_mid_i2c_address_neq - To check if the addresses for different i2c messages + * are equal. + * @p1: first i2c_msg + * @p2: second i2c_msg + * + * Return Values: + * 0 if addresses are equal + * 1 if not equal + * + * Within a single transfer, the I2C client may need to send its address more + * than once. So a check if the addresses match is needed. + */ +static inline bool intel_mid_i2c_address_neq(const struct i2c_msg *p1, + const struct i2c_msg *p2) +{ + if (p1->addr != p2->addr) + return 1; + if ((p1->flags ^ p2->flags) & I2C_M_TEN) + return 1; + return 0; +} + +/** + * intel_mid_i2c_abort - To handle transfer abortions and print error messages. + * @adap: i2c_adapter struct pointer + * + * By reading register IC_TX_ABRT_SOURCE, various transfer errors can be + * distingushed. At present, no circumstances have been found out that + * multiple errors would be occured simutaneously, so we simply use the + * register value directly. + * + * At last the error bits are cleared. (Note clear ABRT_SBYTE_NORSTRT bit need + * a few extra steps) + */ +static void intel_mid_i2c_abort(struct intel_mid_i2c_private *i2c) +{ + /* Read about source register */ + int abort = i2c->abort; + struct i2c_adapter *adap = &i2c->adap; + + /* Single transfer error check: + * According to databook, TX/RX FIFOs would be flushed when + * the abort interrupt occured. + */ + if (abort & ABRT_MASTER_DIS) + dev_err(&adap->dev, + "initiate master operation with master mode disabled.\n"); + if (abort & ABRT_10B_RD_NORSTRT) + dev_err(&adap->dev, + "RESTART disabled and master sent READ cmd in 10-bit addressing.\n"); + + if (abort & ABRT_SBYTE_NORSTRT) { + dev_err(&adap->dev, + "RESTART disabled and user is trying to send START byte.\n"); + writel(~ABRT_SBYTE_NORSTRT, i2c->base + IC_TX_ABRT_SOURCE); + writel(RESTART, i2c->base + IC_CON); + writel(~IC_TAR_SPECIAL, i2c->base + IC_TAR); + } + + if (abort & ABRT_SBYTE_ACKDET) + dev_err(&adap->dev, + "START byte was not acknowledged.\n"); + if (abort & ABRT_TXDATA_NOACK) + dev_dbg(&adap->dev, + "No acknowledgement received from slave.\n"); + if (abort & ABRT_10ADDR2_NOACK) + dev_dbg(&adap->dev, + "The 2nd address byte of the 10-bit address was not acknowledged.\n"); + if (abort & ABRT_10ADDR1_NOACK) + dev_dbg(&adap->dev, + "The 1st address byte of 10-bit address was not acknowledged.\n"); + if (abort & ABRT_7B_ADDR_NOACK) + dev_dbg(&adap->dev, + "I2C slave device not acknowledged.\n"); + + /* Clear TX_ABRT bit */ + readl(i2c->base + IC_CLR_TX_ABRT); + i2c->status = STATUS_XFER_ABORT; +} + +/** + * xfer_read - Internal function to implement master read transfer. + * @adap: i2c_adapter struct pointer + * @buf: buffer in i2c_msg + * @length: number of bytes to be read + * + * Return Values: + * 0 if the read transfer succeeds + * -ETIMEDOUT if cannot read the "raw" interrupt register + * -EINVAL if a transfer abort occurred + * + * For every byte, a "READ" command will be loaded into IC_DATA_CMD prior to + * data transfer. The actual "read" operation will be performed if an RX_FULL + * interrupt occurred. + * + * Note there may be two interrupt signals captured, one should read + * IC_RAW_INTR_STAT to separate between errors and actual data. + */ +static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length) +{ + struct intel_mid_i2c_private *i2c = i2c_get_adapdata(adap); + int i = length; + int err; + + if (length >= 256) { + dev_err(&adap->dev, + "I2C FIFO cannot support larger than 256 bytes\n"); + return -EMSGSIZE; + } + + INIT_COMPLETION(i2c->complete); + + readl(i2c->base + IC_CLR_INTR); + writel(0x0044, i2c->base + IC_INTR_MASK); + + i2c->status = STATUS_READ_START; + + while (i--) + writel(IC_RD, i2c->base + IC_DATA_CMD); + + i2c->status = STATUS_READ_START; + err = wait_for_completion_interruptible_timeout(&i2c->complete, HZ); + if (!err) { + dev_err(&adap->dev, "Timeout for ACK from I2C slave device\n"); + intel_mid_i2c_hwinit(i2c); + return -ETIMEDOUT; + } + if (i2c->status == STATUS_READ_SUCCESS) + return 0; + else + return -EIO; +} + +/** + * xfer_write - Internal function to implement master write transfer. + * @adap: i2c_adapter struct pointer + * @buf: buffer in i2c_msg + * @length: number of bytes to be read + * + * Return Values: + * 0 if the read transfer succeeds + * -ETIMEDOUT if we cannot read the "raw" interrupt register + * -EINVAL if a transfer abort occured + * + * For every byte, a "WRITE" command will be loaded into IC_DATA_CMD prior to + * data transfer. The actual "write" operation will be performed when the + * RX_FULL interrupt signal occurs. + * + * Note there may be two interrupt signals captured, one should read + * IC_RAW_INTR_STAT to separate between errors and actual data. + */ +static int xfer_write(struct i2c_adapter *adap, + unsigned char *buf, int length) +{ + struct intel_mid_i2c_private *i2c = i2c_get_adapdata(adap); + int i, err; + + if (length >= 256) { + dev_err(&adap->dev, + "I2C FIFO cannot support larger than 256 bytes\n"); + return -EMSGSIZE; + } + + INIT_COMPLETION(i2c->complete); + + readl(i2c->base + IC_CLR_INTR); + writel(0x0050, i2c->base + IC_INTR_MASK); + + i2c->status = STATUS_WRITE_START; + for (i = 0; i < length; i++) + writel((u16)(*(buf + i)), i2c->base + IC_DATA_CMD); + + i2c->status = STATUS_WRITE_START; + err = wait_for_completion_interruptible_timeout(&i2c->complete, HZ); + if (!err) { + dev_err(&adap->dev, "Timeout for ACK from I2C slave device\n"); + intel_mid_i2c_hwinit(i2c); + return -ETIMEDOUT; + } else { + if (i2c->status == STATUS_WRITE_SUCCESS) + return 0; + else + return -EIO; + } +} + +static int intel_mid_i2c_setup(struct i2c_adapter *adap, struct i2c_msg *pmsg) +{ + struct intel_mid_i2c_private *i2c = i2c_get_adapdata(adap); + int err; + u32 reg; + u32 bit_mask; + u32 mode; + + /* Disable device first */ + err = intel_mid_i2c_disable(adap); + if (err) { + dev_err(&adap->dev, + "Cannot disable i2c controller, timeout\n"); + return err; + } + + mode = (1 + i2c->speed) << 1; + /* set the speed mode */ + reg = readl(i2c->base + IC_CON); + if ((reg & 0x06) != mode) { + dev_dbg(&adap->dev, "set mode %d\n", i2c->speed); + writel((reg & ~0x6) | mode, i2c->base + IC_CON); + } + + reg = readl(i2c->base + IC_CON); + /* use 7-bit addressing */ + if (pmsg->flags & I2C_M_TEN) { + if ((reg & ADDR_10BIT) != ADDR_10BIT) { + dev_dbg(&adap->dev, "set i2c 10 bit address mode\n"); + writel(reg | ADDR_10BIT, i2c->base + IC_CON); + } + } else { + if ((reg & ADDR_10BIT) != 0x0) { + dev_dbg(&adap->dev, "set i2c 7 bit address mode\n"); + writel(reg & ~ADDR_10BIT, i2c->base + IC_CON); + } + } + /* enable restart conditions */ + reg = readl(i2c->base + IC_CON); + if ((reg & RESTART) != RESTART) { + dev_dbg(&adap->dev, "enable restart conditions\n"); + writel(reg | RESTART, i2c->base + IC_CON); + } + + /* enable master FSM */ + reg = readl(i2c->base + IC_CON); + dev_dbg(&adap->dev, "ic_con reg is 0x%x\n", reg); + writel(reg | MASTER_EN, i2c->base + IC_CON); + if ((reg & SLV_DIS) != SLV_DIS) { + dev_dbg(&adap->dev, "enable master FSM\n"); + writel(reg | SLV_DIS, i2c->base + IC_CON); + dev_dbg(&adap->dev, "ic_con reg is 0x%x\n", reg); + } + + /* use target address when initiating transfer */ + reg = readl(i2c->base + IC_TAR); + bit_mask = IC_TAR_SPECIAL | IC_TAR_GC_OR_START; + + if ((reg & bit_mask) != 0x0) { + dev_dbg(&adap->dev, + "WR: use target address when intiating transfer, i2c_tx_target\n"); + writel(reg & ~bit_mask, i2c->base + IC_TAR); + } + + /* set target address to the I2C slave address */ + dev_dbg(&adap->dev, + "set target address to the I2C slave address, addr is %x\n", + pmsg->addr); + writel(pmsg->addr | (pmsg->flags & I2C_M_TEN ? IC_TAR_10BIT_ADDR : 0), + i2c->base + IC_TAR); + + /* Enable I2C controller */ + writel(ENABLE, i2c->base + IC_ENABLE); + + return 0; +} + +/** + * intel_mid_i2c_xfer - Main master transfer routine. + * @adap: i2c_adapter struct pointer + * @pmsg: i2c_msg struct pointer + * @num: number of i2c_msg + * + * Return Values: + * + number of messages transfered + * -ETIMEDOUT If cannot disable I2C controller or read IC_STATUS + * -EINVAL If the address in i2c_msg is invalid + * + * This function will be registered in i2c-core and exposed to external + * I2C clients. + * 1. Disable I2C controller + * 2. Unmask three interrupts: RX_FULL, TX_EMPTY, TX_ABRT + * 3. Check if address in i2c_msg is valid + * 4. Enable I2C controller + * 5. Perform real transfer (call xfer_read or xfer_write) + * 6. Wait until the current transfer is finished (check bus state) + * 7. Mask and clear all interrupts + */ +static int intel_mid_i2c_xfer(struct i2c_adapter *adap, + struct i2c_msg *pmsg, + int num) +{ + struct intel_mid_i2c_private *i2c = i2c_get_adapdata(adap); + int i, err = 0; + + /* if number of messages equal 0*/ + if (num == 0) + return 0; + + pm_runtime_get(i2c->dev); + + mutex_lock(&i2c->lock); + dev_dbg(&adap->dev, "intel_mid_i2c_xfer, process %d msg(s)\n", num); + dev_dbg(&adap->dev, "slave address is %x\n", pmsg->addr); + + + if (i2c->status != STATUS_IDLE) { + dev_err(&adap->dev, "Adapter %d in transfer/standby\n", + adap->nr); + mutex_unlock(&i2c->lock); + pm_runtime_put(i2c->dev); + return -1; + } + + + for (i = 1; i < num; i++) { + /* Message address equal? */ + if (unlikely(intel_mid_i2c_address_neq(&pmsg[0], &pmsg[i]))) { + dev_err(&adap->dev, "Invalid address in msg[%d]\n", i); + mutex_unlock(&i2c->lock); + pm_runtime_put(i2c->dev); + return -EINVAL; + } + } + + if (intel_mid_i2c_setup(adap, pmsg)) { + mutex_unlock(&i2c->lock); + pm_runtime_put(i2c->dev); + return -EINVAL; + } + + for (i = 0; i < num; i++) { + i2c->msg = pmsg; + i2c->status = STATUS_IDLE; + /* Read or Write */ + if (pmsg->flags & I2C_M_RD) { + dev_dbg(&adap->dev, "I2C_M_RD\n"); + err = xfer_read(adap, pmsg->buf, pmsg->len); + } else { + dev_dbg(&adap->dev, "I2C_M_WR\n"); + err = xfer_write(adap, pmsg->buf, pmsg->len); + } + if (err < 0) + break; + dev_dbg(&adap->dev, "msg[%d] transfer complete\n", i); + pmsg++; /* next message */ + } + + /* Mask interrupts */ + writel(0x0000, i2c->base + IC_INTR_MASK); + /* Clear all interrupts */ + readl(i2c->base + IC_CLR_INTR); + + i2c->status = STATUS_IDLE; + mutex_unlock(&i2c->lock); + pm_runtime_put(i2c->dev); + + return err; +} + +static int intel_mid_i2c_runtime_suspend(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct intel_mid_i2c_private *i2c = pci_get_drvdata(pdev); + struct i2c_adapter *adap = to_i2c_adapter(dev); + int err; + + if (i2c->status != STATUS_IDLE) + return -1; + + intel_mid_i2c_disable(adap); + + err = pci_save_state(pdev); + if (err) { + dev_err(dev, "pci_save_state failed\n"); + return err; + } + + err = pci_set_power_state(pdev, PCI_D3hot); + if (err) { + dev_err(dev, "pci_set_power_state failed\n"); + return err; + } + i2c->status = STATUS_STANDBY; + + return 0; +} + +static int intel_mid_i2c_runtime_resume(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct intel_mid_i2c_private *i2c = pci_get_drvdata(pdev); + int err; + + if (i2c->status != STATUS_STANDBY) + return 0; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + err = pci_enable_device(pdev); + if (err) { + dev_err(dev, "pci_enable_device failed\n"); + return err; + } + + i2c->status = STATUS_IDLE; + + intel_mid_i2c_hwinit(i2c); + return err; +} + +static void i2c_isr_read(struct intel_mid_i2c_private *i2c) +{ + struct i2c_msg *msg = i2c->msg; + int rx_num; + u32 len; + u8 *buf; + + if (!(msg->flags & I2C_M_RD)) + return; + + if (i2c->status != STATUS_READ_IN_PROGRESS) { + len = msg->len; + buf = msg->buf; + } else { + len = i2c->rx_buf_len; + buf = i2c->rx_buf; + } + + rx_num = readl(i2c->base + IC_RXFLR); + + for (; len > 0 && rx_num > 0; len--, rx_num--) + *buf++ = readl(i2c->base + IC_DATA_CMD); + + if (len > 0) { + i2c->status = STATUS_READ_IN_PROGRESS; + i2c->rx_buf_len = len; + i2c->rx_buf = buf; + } else + i2c->status = STATUS_READ_SUCCESS; + + return; +} + +static irqreturn_t intel_mid_i2c_isr(int this_irq, void *dev) +{ + struct intel_mid_i2c_private *i2c = dev; + u32 stat = readl(i2c->base + IC_INTR_STAT); + + if (!stat) + return IRQ_NONE; + + dev_dbg(&i2c->adap.dev, "%s, stat = 0x%x\n", __func__, stat); + stat &= 0x54; + + if (i2c->status != STATUS_WRITE_START && + i2c->status != STATUS_READ_START && + i2c->status != STATUS_READ_IN_PROGRESS) + goto err; + + if (stat & TX_ABRT) + i2c->abort = readl(i2c->base + IC_TX_ABRT_SOURCE); + + readl(i2c->base + IC_CLR_INTR); + + if (stat & TX_ABRT) { + intel_mid_i2c_abort(i2c); + goto exit; + } + + if (stat & RX_FULL) { + i2c_isr_read(i2c); + goto exit; + } + + if (stat & TX_EMPTY) { + if (readl(i2c->base + IC_STATUS) & 0x4) + i2c->status = STATUS_WRITE_SUCCESS; + } + +exit: + if (i2c->status == STATUS_READ_SUCCESS || + i2c->status == STATUS_WRITE_SUCCESS || + i2c->status == STATUS_XFER_ABORT) { + /* Clear all interrupts */ + readl(i2c->base + IC_CLR_INTR); + /* Mask interrupts */ + writel(0, i2c->base + IC_INTR_MASK); + complete(&i2c->complete); + } +err: + return IRQ_HANDLED; +} + +static struct i2c_algorithm intel_mid_i2c_algorithm = { + .master_xfer = intel_mid_i2c_xfer, + .functionality = intel_mid_i2c_func, +}; + + +static const struct dev_pm_ops intel_mid_i2c_pm_ops = { + .runtime_suspend = intel_mid_i2c_runtime_suspend, + .runtime_resume = intel_mid_i2c_runtime_resume, +}; + +/** + * intel_mid_i2c_probe - I2C controller initialization routine + * @dev: pci device + * @id: device id + * + * Return Values: + * 0 success + * -ENODEV If cannot allocate pci resource + * -ENOMEM If the register base remapping failed, or + * if kzalloc failed + * + * Initialization steps: + * 1. Request for PCI resource + * 2. Remap the start address of PCI resource to register base + * 3. Request for device memory region + * 4. Fill in the struct members of intel_mid_i2c_private + * 5. Call intel_mid_i2c_hwinit() for hardware initialization + * 6. Register I2C adapter in i2c-core + */ +static int __devinit intel_mid_i2c_probe(struct pci_dev *dev, + const struct pci_device_id *id) +{ + struct intel_mid_i2c_private *mrst; + unsigned long start, len; + int err, busnum; + void __iomem *base = NULL; + + dev_dbg(&dev->dev, "Get into probe function for I2C\n"); + err = pci_enable_device(dev); + if (err) { + dev_err(&dev->dev, "Failed to enable I2C PCI device (%d)\n", + err); + goto exit; + } + + /* Determine the address of the I2C area */ + start = pci_resource_start(dev, 0); + len = pci_resource_len(dev, 0); + if (!start || len == 0) { + dev_err(&dev->dev, "base address not set\n"); + err = -ENODEV; + goto exit; + } + dev_dbg(&dev->dev, "%s i2c resource start 0x%lx, len=%ld\n", + PLATFORM, start, len); + + err = pci_request_region(dev, 0, DRIVER_NAME); + if (err) { + dev_err(&dev->dev, "failed to request I2C region " + "0x%lx-0x%lx\n", start, + (unsigned long)pci_resource_end(dev, 0)); + goto exit; + } + + base = ioremap_nocache(start, len); + if (!base) { + dev_err(&dev->dev, "I/O memory remapping failed\n"); + err = -ENOMEM; + goto fail0; + } + + /* Allocate the per-device data structure, intel_mid_i2c_private */ + mrst = kzalloc(sizeof(struct intel_mid_i2c_private), GFP_KERNEL); + if (mrst == NULL) { + dev_err(&dev->dev, "can't allocate interface\n"); + err = -ENOMEM; + goto fail1; + } + + /* Initialize struct members */ + snprintf(mrst->adap.name, sizeof(mrst->adap.name), + "MRST/Medfield I2C at %lx", start); + mrst->adap.owner = THIS_MODULE; + mrst->adap.algo = &intel_mid_i2c_algorithm; + mrst->adap.dev.parent = &dev->dev; + mrst->dev = &dev->dev; + mrst->base = base; + mrst->speed = STANDARD; + mrst->abort = 0; + mrst->rx_buf_len = 0; + mrst->status = STATUS_IDLE; + + pci_set_drvdata(dev, mrst); + i2c_set_adapdata(&mrst->adap, mrst); + + mrst->adap.nr = busnum = id->driver_data; + if (dev->device <= 0x0804) + mrst->platform = MOORESTOWN; + else + mrst->platform = MEDFIELD; + + dev_dbg(&dev->dev, "I2C%d\n", busnum); + + if (ctl_num > busnum) { + if (speed_mode[busnum] < 0 || speed_mode[busnum] >= NUM_SPEEDS) + dev_warn(&dev->dev, "invalid speed %d ignored.\n", + speed_mode[busnum]); + else + mrst->speed = speed_mode[busnum]; + } + + /* Initialize i2c controller */ + err = intel_mid_i2c_hwinit(mrst); + if (err < 0) { + dev_err(&dev->dev, "I2C interface initialization failed\n"); + goto fail2; + } + + mutex_init(&mrst->lock); + init_completion(&mrst->complete); + + /* Clear all interrupts */ + readl(mrst->base + IC_CLR_INTR); + writel(0x0000, mrst->base + IC_INTR_MASK); + + err = request_irq(dev->irq, intel_mid_i2c_isr, IRQF_SHARED, + mrst->adap.name, mrst); + if (err) { + dev_err(&dev->dev, "Failed to request IRQ for I2C controller: " + "%s", mrst->adap.name); + goto fail2; + } + + /* Adapter registration */ + err = i2c_add_numbered_adapter(&mrst->adap); + if (err) { + dev_err(&dev->dev, "Adapter %s registration failed\n", + mrst->adap.name); + goto fail3; + } + + dev_dbg(&dev->dev, "%s I2C bus %d driver bind success.\n", + (mrst->platform == MOORESTOWN) ? "Moorestown" : "Medfield", + busnum); + + pm_runtime_enable(&dev->dev); + return 0; + +fail3: + free_irq(dev->irq, mrst); +fail2: + pci_set_drvdata(dev, NULL); + kfree(mrst); +fail1: + iounmap(base); +fail0: + pci_release_region(dev, 0); +exit: + return err; +} + +static void __devexit intel_mid_i2c_remove(struct pci_dev *dev) +{ + struct intel_mid_i2c_private *mrst = pci_get_drvdata(dev); + intel_mid_i2c_disable(&mrst->adap); + if (i2c_del_adapter(&mrst->adap)) + dev_err(&dev->dev, "Failed to delete i2c adapter"); + + free_irq(dev->irq, mrst); + pci_set_drvdata(dev, NULL); + iounmap(mrst->base); + kfree(mrst); + pci_release_region(dev, 0); +} + +static struct pci_device_id intel_mid_i2c_ids[] = { + /* Moorestown */ + { PCI_VDEVICE(INTEL, 0x0802), 0 }, + { PCI_VDEVICE(INTEL, 0x0803), 1 }, + { PCI_VDEVICE(INTEL, 0x0804), 2 }, + /* Medfield */ + { PCI_VDEVICE(INTEL, 0x0817), 3,}, + { PCI_VDEVICE(INTEL, 0x0818), 4 }, + { PCI_VDEVICE(INTEL, 0x0819), 5 }, + { PCI_VDEVICE(INTEL, 0x082C), 0 }, + { PCI_VDEVICE(INTEL, 0x082D), 1 }, + { PCI_VDEVICE(INTEL, 0x082E), 2 }, + { 0,} +}; +MODULE_DEVICE_TABLE(pci, intel_mid_i2c_ids); + +static struct pci_driver intel_mid_i2c_driver = { + .name = DRIVER_NAME, + .id_table = intel_mid_i2c_ids, + .probe = intel_mid_i2c_probe, + .remove = __devexit_p(intel_mid_i2c_remove), +}; + +static int __init intel_mid_i2c_init(void) +{ + return pci_register_driver(&intel_mid_i2c_driver); +} + +static void __exit intel_mid_i2c_exit(void) +{ + pci_unregister_driver(&intel_mid_i2c_driver); +} + +module_init(intel_mid_i2c_init); +module_exit(intel_mid_i2c_exit); + +MODULE_AUTHOR("Ba Zheng <zheng.ba@intel.com>"); +MODULE_DESCRIPTION("I2C driver for Moorestown Platform"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(VERSION); diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 73de8ade10b1..c9fffd0389fe 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 ST-Ericsson + * Copyright (C) 2009 ST-Ericsson SA * Copyright (C) 2009 STMicroelectronics * * I2C master mode controller driver, used in Nomadik 8815 @@ -103,6 +103,9 @@ /* maximum threshold value */ #define MAX_I2C_FIFO_THRESHOLD 15 +/* per-transfer delay, required for the hardware to stabilize */ +#define I2C_DELAY 150 + enum i2c_status { I2C_NOP, I2C_ON_GOING, @@ -118,7 +121,7 @@ enum i2c_operation { }; /* controller response timeout in ms */ -#define I2C_TIMEOUT_MS 500 +#define I2C_TIMEOUT_MS 2000 /** * struct i2c_nmk_client - client specific data @@ -250,6 +253,8 @@ static int init_hw(struct nmk_i2c_dev *dev) { int stat; + clk_enable(dev->clk); + stat = flush_i2c_fifo(dev); if (stat) return stat; @@ -263,6 +268,9 @@ static int init_hw(struct nmk_i2c_dev *dev) dev->cli.operation = I2C_NO_OPERATION; + clk_disable(dev->clk); + + udelay(I2C_DELAY); return 0; } @@ -431,7 +439,6 @@ static int read_i2c(struct nmk_i2c_dev *dev) (void) init_hw(dev); status = -ETIMEDOUT; } - return status; } @@ -502,9 +509,9 @@ static int write_i2c(struct nmk_i2c_dev *dev) /** * nmk_i2c_xfer() - I2C transfer function used by kernel framework - * @i2c_adap - Adapter pointer to the controller - * @msgs[] - Pointer to data to be written. - * @num_msgs - Number of messages to be executed + * @i2c_adap: Adapter pointer to the controller + * @msgs: Pointer to data to be written. + * @num_msgs: Number of messages to be executed * * This is the function called by the generic kernel i2c_transfer() * or i2c_smbus...() API calls. Note that this code is protected by the @@ -559,6 +566,8 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, if (status) return status; + clk_enable(dev->clk); + /* setup the i2c controller */ setup_i2c_controller(dev); @@ -591,10 +600,13 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, dev_err(&dev->pdev->dev, "%s\n", cause >= ARRAY_SIZE(abort_causes) ? "unknown reason" : abort_causes[cause]); + clk_disable(dev->clk); return status; } - mdelay(1); + udelay(I2C_DELAY); } + clk_disable(dev->clk); + /* return the no. messages processed */ if (status) return status; @@ -605,6 +617,7 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, /** * disable_interrupts() - disable the interrupts * @dev: private data of controller + * @irq: interrupt number */ static int disable_interrupts(struct nmk_i2c_dev *dev, u32 irq) { @@ -794,10 +807,7 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg) static unsigned int nmk_i2c_functionality(struct i2c_adapter *adap) { - return I2C_FUNC_I2C - | I2C_FUNC_SMBUS_BYTE_DATA - | I2C_FUNC_SMBUS_WORD_DATA - | I2C_FUNC_SMBUS_I2C_BLOCK; + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; } static const struct i2c_algorithm nmk_i2c_algo = { @@ -857,8 +867,6 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev) goto err_no_clk; } - clk_enable(dev->clk); - adap = &dev->adap; adap->dev.parent = &pdev->dev; adap->owner = THIS_MODULE; @@ -895,7 +903,6 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev) return 0; err_init_hw: - clk_disable(dev->clk); err_add_adap: clk_put(dev->clk); err_no_clk: @@ -928,7 +935,6 @@ static int __devexit nmk_i2c_remove(struct platform_device *pdev) iounmap(dev->virtbase); if (res) release_mem_region(res->start, resource_size(res)); - clk_disable(dev->clk); clk_put(dev->clk); platform_set_drvdata(pdev, NULL); kfree(dev); diff --git a/drivers/i2c/busses/i2c-nuc900.c b/drivers/i2c/busses/i2c-nuc900.c index 92d770d7bbc2..72434263787b 100644 --- a/drivers/i2c/busses/i2c-nuc900.c +++ b/drivers/i2c/busses/i2c-nuc900.c @@ -16,7 +16,6 @@ #include <linux/module.h> #include <linux/i2c.h> -#include <linux/i2c-id.h> #include <linux/init.h> #include <linux/time.h> #include <linux/interrupt.h> diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c index 4174101660c9..837b8c1aa02a 100644 --- a/drivers/i2c/busses/i2c-pasemi.c +++ b/drivers/i2c/busses/i2c-pasemi.c @@ -88,7 +88,7 @@ static void pasemi_smb_clear(struct pasemi_smbus *smbus) reg_write(smbus, REG_SMSTA, status); } -static unsigned int pasemi_smb_waitready(struct pasemi_smbus *smbus) +static int pasemi_smb_waitready(struct pasemi_smbus *smbus) { int timeout = 10; unsigned int status; diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c index 5f6d7f89e225..ace67995d7de 100644 --- a/drivers/i2c/busses/i2c-pca-platform.c +++ b/drivers/i2c/busses/i2c-pca-platform.c @@ -224,7 +224,7 @@ static int __devinit i2c_pca_pf_probe(struct platform_device *pdev) if (irq) { ret = request_irq(irq, i2c_pca_pf_handler, - IRQF_TRIGGER_FALLING, i2c->adap.name, i2c); + IRQF_TRIGGER_FALLING, pdev->name, i2c); if (ret) goto e_reqirq; } diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index c94e51b2651e..f4c19a97e0b3 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -22,7 +22,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/i2c.h> -#include <linux/i2c-id.h> #include <linux/init.h> #include <linux/time.h> #include <linux/sched.h> diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index bf831bf81587..6c00c107ebf3 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -24,7 +24,6 @@ #include <linux/module.h> #include <linux/i2c.h> -#include <linux/i2c-id.h> #include <linux/init.h> #include <linux/time.h> #include <linux/interrupt.h> @@ -555,18 +554,23 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap, int retry; int ret; + clk_enable(i2c->clk); + for (retry = 0; retry < adap->retries; retry++) { ret = s3c24xx_i2c_doxfer(i2c, msgs, num); - if (ret != -EAGAIN) + if (ret != -EAGAIN) { + clk_disable(i2c->clk); return ret; + } dev_dbg(i2c->dev, "Retrying transmission (%d)\n", retry); udelay(100); } + clk_disable(i2c->clk); return -EREMOTEIO; } @@ -911,6 +915,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) platform_set_drvdata(pdev, i2c); dev_info(&pdev->dev, "%s: S3C I2C adapter\n", dev_name(&i2c->adap.dev)); + clk_disable(i2c->clk); return 0; err_cpufreq: @@ -978,7 +983,9 @@ static int s3c24xx_i2c_resume(struct device *dev) struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev); i2c->suspended = 0; + clk_enable(i2c->clk); s3c24xx_i2c_init(i2c); + clk_disable(i2c->clk); return 0; } diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c index 4f93da31d3ad..3cad8fecc3d3 100644 --- a/drivers/i2c/busses/i2c-sh7760.c +++ b/drivers/i2c/busses/i2c-sh7760.c @@ -101,12 +101,12 @@ struct cami2c { static inline void OUT32(struct cami2c *cam, int reg, unsigned long val) { - ctrl_outl(val, (unsigned long)cam->iobase + reg); + __raw_writel(val, (unsigned long)cam->iobase + reg); } static inline unsigned long IN32(struct cami2c *cam, int reg) { - return ctrl_inl((unsigned long)cam->iobase + reg); + return __raw_readl((unsigned long)cam->iobase + reg); } static irqreturn_t sh7760_i2c_irq(int irq, void *ptr) diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 598c49acaeb5..2707f5e17158 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -538,15 +538,17 @@ static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook) { struct resource *res; int ret = -ENXIO; - int q, m; - int k = 0; - int n = 0; + int n, k = 0; while ((res = platform_get_resource(dev, IORESOURCE_IRQ, k))) { for (n = res->start; hook && n <= res->end; n++) { if (request_irq(n, sh_mobile_i2c_isr, IRQF_DISABLED, - dev_name(&dev->dev), dev)) + dev_name(&dev->dev), dev)) { + for (n--; n >= res->start; n--) + free_irq(n, dev); + goto rollback; + } } k++; } @@ -554,16 +556,17 @@ static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook) if (hook) return k > 0 ? 0 : -ENOENT; - k--; ret = 0; rollback: - for (q = k; k >= 0; k--) { - for (m = n; m >= res->start; m--) - free_irq(m, dev); + k--; + + while (k >= 0) { + res = platform_get_resource(dev, IORESOURCE_IRQ, k); + for (n = res->start; n <= res->end; n++) + free_irq(n, dev); - res = platform_get_resource(dev, IORESOURCE_IRQ, k - 1); - m = res->end; + k--; } return ret; diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c index 4c6fff5f330d..0b012f1f8ac5 100644 --- a/drivers/i2c/busses/i2c-viapro.c +++ b/drivers/i2c/busses/i2c-viapro.c @@ -185,14 +185,8 @@ static int vt596_transaction(u8 size) } if (temp & 0x04) { - int read = inb_p(SMBHSTADD) & 0x01; result = -ENXIO; - /* The quick and receive byte commands are used to probe - for chips, so errors are expected, and we don't want - to frighten the user. */ - if (!((size == VT596_QUICK && !read) || - (size == VT596_BYTE && read))) - dev_err(&vt596_adapter.dev, "Transaction error!\n"); + dev_dbg(&vt596_adapter.dev, "No response\n"); } /* Resetting status register */ diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index 4cb4bb009950..53fab518b3da 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -560,7 +560,8 @@ static const struct pci_device_id scx200_pci[] __initconst = { { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA), .driver_data = 1 }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA), - .driver_data = 2 } + .driver_data = 2 }, + { 0, } }; static struct { diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index bea4c5021d26..6b4cc567645b 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -425,14 +425,14 @@ static int __i2c_check_addr_busy(struct device *dev, void *addrp) /* walk up mux tree */ static int i2c_check_mux_parents(struct i2c_adapter *adapter, int addr) { + struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); int result; result = device_for_each_child(&adapter->dev, &addr, __i2c_check_addr_busy); - if (!result && i2c_parent_is_i2c_adapter(adapter)) - result = i2c_check_mux_parents( - to_i2c_adapter(adapter->dev.parent), addr); + if (!result && parent) + result = i2c_check_mux_parents(parent, addr); return result; } @@ -453,11 +453,11 @@ static int i2c_check_mux_children(struct device *dev, void *addrp) static int i2c_check_addr_busy(struct i2c_adapter *adapter, int addr) { + struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); int result = 0; - if (i2c_parent_is_i2c_adapter(adapter)) - result = i2c_check_mux_parents( - to_i2c_adapter(adapter->dev.parent), addr); + if (parent) + result = i2c_check_mux_parents(parent, addr); if (!result) result = device_for_each_child(&adapter->dev, &addr, @@ -472,8 +472,10 @@ static int i2c_check_addr_busy(struct i2c_adapter *adapter, int addr) */ void i2c_lock_adapter(struct i2c_adapter *adapter) { - if (i2c_parent_is_i2c_adapter(adapter)) - i2c_lock_adapter(to_i2c_adapter(adapter->dev.parent)); + struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); + + if (parent) + i2c_lock_adapter(parent); else rt_mutex_lock(&adapter->bus_lock); } @@ -485,8 +487,10 @@ EXPORT_SYMBOL_GPL(i2c_lock_adapter); */ static int i2c_trylock_adapter(struct i2c_adapter *adapter) { - if (i2c_parent_is_i2c_adapter(adapter)) - return i2c_trylock_adapter(to_i2c_adapter(adapter->dev.parent)); + struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); + + if (parent) + return i2c_trylock_adapter(parent); else return rt_mutex_trylock(&adapter->bus_lock); } @@ -497,8 +501,10 @@ static int i2c_trylock_adapter(struct i2c_adapter *adapter) */ void i2c_unlock_adapter(struct i2c_adapter *adapter) { - if (i2c_parent_is_i2c_adapter(adapter)) - i2c_unlock_adapter(to_i2c_adapter(adapter->dev.parent)); + struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); + + if (parent) + i2c_unlock_adapter(parent); else rt_mutex_unlock(&adapter->bus_lock); } @@ -677,8 +683,6 @@ i2c_sysfs_new_device(struct device *dev, struct device_attribute *attr, char *blank, end; int res; - dev_warn(dev, "The new_device interface is still experimental " - "and may change in a near future\n"); memset(&info, 0, sizeof(struct i2c_board_info)); blank = strchr(buf, ' '); @@ -844,6 +848,18 @@ static int i2c_register_adapter(struct i2c_adapter *adap) goto out_list; } + /* Sanity checks */ + if (unlikely(adap->name[0] == '\0')) { + pr_err("i2c-core: Attempt to register an adapter with " + "no name!\n"); + return -EINVAL; + } + if (unlikely(!adap->algo)) { + pr_err("i2c-core: Attempt to register adapter '%s' with " + "no algo!\n", adap->name); + return -EINVAL; + } + rt_mutex_init(&adap->bus_lock); mutex_init(&adap->userspace_clients_lock); INIT_LIST_HEAD(&adap->userspace_clients); @@ -1504,26 +1520,25 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver) if (!driver->detect || !address_list) return 0; + /* Stop here if the classes do not match */ + if (!(adapter->class & driver->class)) + return 0; + /* Set up a temporary client to help detect callback */ temp_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); if (!temp_client) return -ENOMEM; temp_client->adapter = adapter; - /* Stop here if the classes do not match */ - if (!(adapter->class & driver->class)) - goto exit_free; - for (i = 0; address_list[i] != I2C_CLIENT_END; i += 1) { dev_dbg(&adapter->dev, "found normal entry for adapter %d, " "addr 0x%02x\n", adap_id, address_list[i]); temp_client->addr = address_list[i]; err = i2c_detect_address(temp_client, driver); - if (err) - goto exit_free; + if (unlikely(err)) + break; } - exit_free: kfree(temp_client); return err; } diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 5f3a52d517c3..cec0f3ba97f8 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -192,13 +192,12 @@ static int i2cdev_check(struct device *dev, void *addrp) /* walk up mux tree */ static int i2cdev_check_mux_parents(struct i2c_adapter *adapter, int addr) { + struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); int result; result = device_for_each_child(&adapter->dev, &addr, i2cdev_check); - - if (!result && i2c_parent_is_i2c_adapter(adapter)) - result = i2cdev_check_mux_parents( - to_i2c_adapter(adapter->dev.parent), addr); + if (!result && parent) + result = i2cdev_check_mux_parents(parent, addr); return result; } @@ -222,11 +221,11 @@ static int i2cdev_check_mux_children(struct device *dev, void *addrp) driver bound to it, as NOT busy. */ static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr) { + struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); int result = 0; - if (i2c_parent_is_i2c_adapter(adapter)) - result = i2cdev_check_mux_parents( - to_i2c_adapter(adapter->dev.parent), addr); + if (parent) + result = i2cdev_check_mux_parents(parent, addr); if (!result) result = device_for_each_child(&adapter->dev, &addr, diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c index d32a4843fc3a..d7a4833be416 100644 --- a/drivers/i2c/i2c-mux.c +++ b/drivers/i2c/i2c-mux.c @@ -120,7 +120,6 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, snprintf(priv->adap.name, sizeof(priv->adap.name), "i2c-%d-mux (chan_id %d)", i2c_adapter_id(parent), chan_id); priv->adap.owner = THIS_MODULE; - priv->adap.id = parent->id; priv->adap.algo = &priv->algo; priv->adap.algo_data = priv; priv->adap.dev.parent = &parent->dev; diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig index 4c9a99c4fcb0..4d91d80bfd23 100644 --- a/drivers/i2c/muxes/Kconfig +++ b/drivers/i2c/muxes/Kconfig @@ -5,6 +5,16 @@ menu "Multiplexer I2C Chip support" depends on I2C_MUX +config I2C_MUX_PCA9541 + tristate "NXP PCA9541 I2C Master Selector" + depends on EXPERIMENTAL + help + If you say yes here you get support for the NXP PCA9541 + I2C Master Selector. + + This driver can also be built as a module. If so, the module + will be called pca9541. + config I2C_MUX_PCA954x tristate "Philips PCA954x I2C Mux/switches" depends on EXPERIMENTAL diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile index bd83b5274815..d743806d9b42 100644 --- a/drivers/i2c/muxes/Makefile +++ b/drivers/i2c/muxes/Makefile @@ -1,8 +1,7 @@ # # Makefile for multiplexer I2C chip drivers. +obj-$(CONFIG_I2C_MUX_PCA9541) += pca9541.o obj-$(CONFIG_I2C_MUX_PCA954x) += pca954x.o -ifeq ($(CONFIG_I2C_DEBUG_BUS),y) -EXTRA_CFLAGS += -DDEBUG -endif +ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG diff --git a/drivers/i2c/muxes/pca9541.c b/drivers/i2c/muxes/pca9541.c new file mode 100644 index 000000000000..ed699c5aa79d --- /dev/null +++ b/drivers/i2c/muxes/pca9541.c @@ -0,0 +1,411 @@ +/* + * I2C multiplexer driver for PCA9541 bus master selector + * + * Copyright (c) 2010 Ericsson AB. + * + * Author: Guenter Roeck <guenter.roeck@ericsson.com> + * + * Derived from: + * pca954x.c + * + * Copyright (c) 2008-2009 Rodolfo Giometti <giometti@linux.it> + * Copyright (c) 2008-2009 Eurotech S.p.A. <info@eurotech.it> + * + * 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. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/jiffies.h> +#include <linux/delay.h> +#include <linux/slab.h> +#include <linux/device.h> +#include <linux/i2c.h> +#include <linux/i2c-mux.h> + +#include <linux/i2c/pca954x.h> + +/* + * The PCA9541 is a bus master selector. It supports two I2C masters connected + * to a single slave bus. + * + * Before each bus transaction, a master has to acquire bus ownership. After the + * transaction is complete, bus ownership has to be released. This fits well + * into the I2C multiplexer framework, which provides select and release + * functions for this purpose. For this reason, this driver is modeled as + * single-channel I2C bus multiplexer. + * + * This driver assumes that the two bus masters are controlled by two different + * hosts. If a single host controls both masters, platform code has to ensure + * that only one of the masters is instantiated at any given time. + */ + +#define PCA9541_CONTROL 0x01 +#define PCA9541_ISTAT 0x02 + +#define PCA9541_CTL_MYBUS (1 << 0) +#define PCA9541_CTL_NMYBUS (1 << 1) +#define PCA9541_CTL_BUSON (1 << 2) +#define PCA9541_CTL_NBUSON (1 << 3) +#define PCA9541_CTL_BUSINIT (1 << 4) +#define PCA9541_CTL_TESTON (1 << 6) +#define PCA9541_CTL_NTESTON (1 << 7) + +#define PCA9541_ISTAT_INTIN (1 << 0) +#define PCA9541_ISTAT_BUSINIT (1 << 1) +#define PCA9541_ISTAT_BUSOK (1 << 2) +#define PCA9541_ISTAT_BUSLOST (1 << 3) +#define PCA9541_ISTAT_MYTEST (1 << 6) +#define PCA9541_ISTAT_NMYTEST (1 << 7) + +#define BUSON (PCA9541_CTL_BUSON | PCA9541_CTL_NBUSON) +#define MYBUS (PCA9541_CTL_MYBUS | PCA9541_CTL_NMYBUS) +#define mybus(x) (!((x) & MYBUS) || ((x) & MYBUS) == MYBUS) +#define busoff(x) (!((x) & BUSON) || ((x) & BUSON) == BUSON) + +/* arbitration timeouts, in jiffies */ +#define ARB_TIMEOUT (HZ / 8) /* 125 ms until forcing bus ownership */ +#define ARB2_TIMEOUT (HZ / 4) /* 250 ms until acquisition failure */ + +/* arbitration retry delays, in us */ +#define SELECT_DELAY_SHORT 50 +#define SELECT_DELAY_LONG 1000 + +struct pca9541 { + struct i2c_adapter *mux_adap; + unsigned long select_timeout; + unsigned long arb_timeout; +}; + +static const struct i2c_device_id pca9541_id[] = { + {"pca9541", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, pca9541_id); + +/* + * Write to chip register. Don't use i2c_transfer()/i2c_smbus_xfer() + * as they will try to lock the adapter a second time. + */ +static int pca9541_reg_write(struct i2c_client *client, u8 command, u8 val) +{ + struct i2c_adapter *adap = client->adapter; + int ret; + + if (adap->algo->master_xfer) { + struct i2c_msg msg; + char buf[2]; + + msg.addr = client->addr; + msg.flags = 0; + msg.len = 2; + buf[0] = command; + buf[1] = val; + msg.buf = buf; + ret = adap->algo->master_xfer(adap, &msg, 1); + } else { + union i2c_smbus_data data; + + data.byte = val; + ret = adap->algo->smbus_xfer(adap, client->addr, + client->flags, + I2C_SMBUS_WRITE, + command, + I2C_SMBUS_BYTE_DATA, &data); + } + + return ret; +} + +/* + * Read from chip register. Don't use i2c_transfer()/i2c_smbus_xfer() + * as they will try to lock adapter a second time. + */ +static int pca9541_reg_read(struct i2c_client *client, u8 command) +{ + struct i2c_adapter *adap = client->adapter; + int ret; + u8 val; + + if (adap->algo->master_xfer) { + struct i2c_msg msg[2] = { + { + .addr = client->addr, + .flags = 0, + .len = 1, + .buf = &command + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = 1, + .buf = &val + } + }; + ret = adap->algo->master_xfer(adap, msg, 2); + if (ret == 2) + ret = val; + else if (ret >= 0) + ret = -EIO; + } else { + union i2c_smbus_data data; + + ret = adap->algo->smbus_xfer(adap, client->addr, + client->flags, + I2C_SMBUS_READ, + command, + I2C_SMBUS_BYTE_DATA, &data); + if (!ret) + ret = data.byte; + } + return ret; +} + +/* + * Arbitration management functions + */ + +/* Release bus. Also reset NTESTON and BUSINIT if it was set. */ +static void pca9541_release_bus(struct i2c_client *client) +{ + int reg; + + reg = pca9541_reg_read(client, PCA9541_CONTROL); + if (reg >= 0 && !busoff(reg) && mybus(reg)) + pca9541_reg_write(client, PCA9541_CONTROL, + (reg & PCA9541_CTL_NBUSON) >> 1); +} + +/* + * Arbitration is defined as a two-step process. A bus master can only activate + * the slave bus if it owns it; otherwise it has to request ownership first. + * This multi-step process ensures that access contention is resolved + * gracefully. + * + * Bus Ownership Other master Action + * state requested access + * ---------------------------------------------------- + * off - yes wait for arbitration timeout or + * for other master to drop request + * off no no take ownership + * off yes no turn on bus + * on yes - done + * on no - wait for arbitration timeout or + * for other master to release bus + * + * The main contention point occurs if the slave bus is off and both masters + * request ownership at the same time. In this case, one master will turn on + * the slave bus, believing that it owns it. The other master will request + * bus ownership. Result is that the bus is turned on, and master which did + * _not_ own the slave bus before ends up owning it. + */ + +/* Control commands per PCA9541 datasheet */ +static const u8 pca9541_control[16] = { + 4, 0, 1, 5, 4, 4, 5, 5, 0, 0, 1, 1, 0, 4, 5, 1 +}; + +/* + * Channel arbitration + * + * Return values: + * <0: error + * 0 : bus not acquired + * 1 : bus acquired + */ +static int pca9541_arbitrate(struct i2c_client *client) +{ + struct pca9541 *data = i2c_get_clientdata(client); + int reg; + + reg = pca9541_reg_read(client, PCA9541_CONTROL); + if (reg < 0) + return reg; + + if (busoff(reg)) { + int istat; + /* + * Bus is off. Request ownership or turn it on unless + * other master requested ownership. + */ + istat = pca9541_reg_read(client, PCA9541_ISTAT); + if (!(istat & PCA9541_ISTAT_NMYTEST) + || time_is_before_eq_jiffies(data->arb_timeout)) { + /* + * Other master did not request ownership, + * or arbitration timeout expired. Take the bus. + */ + pca9541_reg_write(client, + PCA9541_CONTROL, + pca9541_control[reg & 0x0f] + | PCA9541_CTL_NTESTON); + data->select_timeout = SELECT_DELAY_SHORT; + } else { + /* + * Other master requested ownership. + * Set extra long timeout to give it time to acquire it. + */ + data->select_timeout = SELECT_DELAY_LONG * 2; + } + } else if (mybus(reg)) { + /* + * Bus is on, and we own it. We are done with acquisition. + * Reset NTESTON and BUSINIT, then return success. + */ + if (reg & (PCA9541_CTL_NTESTON | PCA9541_CTL_BUSINIT)) + pca9541_reg_write(client, + PCA9541_CONTROL, + reg & ~(PCA9541_CTL_NTESTON + | PCA9541_CTL_BUSINIT)); + return 1; + } else { + /* + * Other master owns the bus. + * If arbitration timeout has expired, force ownership. + * Otherwise request it. + */ + data->select_timeout = SELECT_DELAY_LONG; + if (time_is_before_eq_jiffies(data->arb_timeout)) { + /* Time is up, take the bus and reset it. */ + pca9541_reg_write(client, + PCA9541_CONTROL, + pca9541_control[reg & 0x0f] + | PCA9541_CTL_BUSINIT + | PCA9541_CTL_NTESTON); + } else { + /* Request bus ownership if needed */ + if (!(reg & PCA9541_CTL_NTESTON)) + pca9541_reg_write(client, + PCA9541_CONTROL, + reg | PCA9541_CTL_NTESTON); + } + } + return 0; +} + +static int pca9541_select_chan(struct i2c_adapter *adap, void *client, u32 chan) +{ + struct pca9541 *data = i2c_get_clientdata(client); + int ret; + unsigned long timeout = jiffies + ARB2_TIMEOUT; + /* give up after this time */ + + data->arb_timeout = jiffies + ARB_TIMEOUT; + /* force bus ownership after this time */ + + do { + ret = pca9541_arbitrate(client); + if (ret) + return ret < 0 ? ret : 0; + + if (data->select_timeout == SELECT_DELAY_SHORT) + udelay(data->select_timeout); + else + msleep(data->select_timeout / 1000); + } while (time_is_after_eq_jiffies(timeout)); + + return -ETIMEDOUT; +} + +static int pca9541_release_chan(struct i2c_adapter *adap, + void *client, u32 chan) +{ + pca9541_release_bus(client); + return 0; +} + +/* + * I2C init/probing/exit functions + */ +static int pca9541_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = client->adapter; + struct pca954x_platform_data *pdata = client->dev.platform_data; + struct pca9541 *data; + int force; + int ret = -ENODEV; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA)) + goto err; + + data = kzalloc(sizeof(struct pca9541), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto err; + } + + i2c_set_clientdata(client, data); + + /* + * I2C accesses are unprotected here. + * We have to lock the adapter before releasing the bus. + */ + i2c_lock_adapter(adap); + pca9541_release_bus(client); + i2c_unlock_adapter(adap); + + /* Create mux adapter */ + + force = 0; + if (pdata) + force = pdata->modes[0].adap_id; + data->mux_adap = i2c_add_mux_adapter(adap, client, force, 0, + pca9541_select_chan, + pca9541_release_chan); + + if (data->mux_adap == NULL) { + dev_err(&client->dev, "failed to register master selector\n"); + goto exit_free; + } + + dev_info(&client->dev, "registered master selector for I2C %s\n", + client->name); + + return 0; + +exit_free: + kfree(data); +err: + return ret; +} + +static int pca9541_remove(struct i2c_client *client) +{ + struct pca9541 *data = i2c_get_clientdata(client); + + i2c_del_mux_adapter(data->mux_adap); + + kfree(data); + return 0; +} + +static struct i2c_driver pca9541_driver = { + .driver = { + .name = "pca9541", + .owner = THIS_MODULE, + }, + .probe = pca9541_probe, + .remove = pca9541_remove, + .id_table = pca9541_id, +}; + +static int __init pca9541_init(void) +{ + return i2c_add_driver(&pca9541_driver); +} + +static void __exit pca9541_exit(void) +{ + i2c_del_driver(&pca9541_driver); +} + +module_init(pca9541_init); +module_exit(pca9541_exit); + +MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>"); +MODULE_DESCRIPTION("PCA9541 I2C master selector driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/i2c/muxes/pca954x.c b/drivers/i2c/muxes/pca954x.c index 6f9accf3189d..54e1ce73534b 100644 --- a/drivers/i2c/muxes/pca954x.c +++ b/drivers/i2c/muxes/pca954x.c @@ -181,8 +181,8 @@ static int pca954x_deselect_mux(struct i2c_adapter *adap, /* * I2C init/probing/exit functions */ -static int __devinit pca954x_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int pca954x_probe(struct i2c_client *client, + const struct i2c_device_id *id) { struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); struct pca954x_platform_data *pdata = client->dev.platform_data; @@ -255,7 +255,7 @@ err: return ret; } -static int __devexit pca954x_remove(struct i2c_client *client) +static int pca954x_remove(struct i2c_client *client) { struct pca954x *data = i2c_get_clientdata(client); const struct chip_desc *chip = &chips[data->type]; @@ -279,7 +279,7 @@ static struct i2c_driver pca954x_driver = { .owner = THIS_MODULE, }, .probe = pca954x_probe, - .remove = __devexit_p(pca954x_remove), + .remove = pca954x_remove, .id_table = pca954x_id, }; |