From 31d178bffcff4c468c8c65bc42d9f4c0a7b8e3ec Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 28 Oct 2012 21:37:00 +0100 Subject: i2c-stub: Move to drivers/i2c Move the i2c-stub driver to drivers/i2c, to match the Kconfig entry. This is less confusing that way. I also fixed all checkpatch warnings and errors. Signed-off-by: Jean Delvare Cc: Peter Huewe --- drivers/i2c/Makefile | 1 + drivers/i2c/busses/Makefile | 1 - drivers/i2c/busses/i2c-stub.c | 222 ------------------------------------------ drivers/i2c/i2c-stub.c | 220 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 221 insertions(+), 223 deletions(-) delete mode 100644 drivers/i2c/busses/i2c-stub.c create mode 100644 drivers/i2c/i2c-stub.c (limited to 'drivers/i2c') diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index beee6b2..1722f50 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o obj-$(CONFIG_I2C_MUX) += i2c-mux.o obj-y += algos/ busses/ muxes/ +obj-$(CONFIG_I2C_STUB) += i2c-stub.o ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG CFLAGS_i2c-core.o := -Wno-deprecated-declarations diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 2d33d62..395b516 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -85,7 +85,6 @@ obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o -obj-$(CONFIG_I2C_STUB) += i2c-stub.o obj-$(CONFIG_SCx200_ACB) += scx200_acb.o obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o diff --git a/drivers/i2c/busses/i2c-stub.c b/drivers/i2c/busses/i2c-stub.c deleted file mode 100644 index b1b34479..0000000 --- a/drivers/i2c/busses/i2c-stub.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - i2c-stub.c - I2C/SMBus chip emulator - - Copyright (c) 2004 Mark M. Hoffman - Copyright (C) 2007 Jean Delvare - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#define DEBUG 1 - -#include -#include -#include -#include -#include -#include - -#define MAX_CHIPS 10 -#define STUB_FUNC (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | \ - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | \ - I2C_FUNC_SMBUS_I2C_BLOCK) - -static unsigned short chip_addr[MAX_CHIPS]; -module_param_array(chip_addr, ushort, NULL, S_IRUGO); -MODULE_PARM_DESC(chip_addr, - "Chip addresses (up to 10, between 0x03 and 0x77)"); - -static unsigned long functionality = STUB_FUNC; -module_param(functionality, ulong, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(functionality, "Override functionality bitfield"); - -struct stub_chip { - u8 pointer; - u16 words[256]; /* Byte operations use the LSB as per SMBus - specification */ -}; - -static struct stub_chip *stub_chips; - -/* Return negative errno on error. */ -static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags, - char read_write, u8 command, int size, union i2c_smbus_data * data) -{ - s32 ret; - int i, len; - struct stub_chip *chip = NULL; - - /* Search for the right chip */ - for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) { - if (addr == chip_addr[i]) { - chip = stub_chips + i; - break; - } - } - if (!chip) - return -ENODEV; - - switch (size) { - - case I2C_SMBUS_QUICK: - dev_dbg(&adap->dev, "smbus quick - addr 0x%02x\n", addr); - ret = 0; - break; - - case I2C_SMBUS_BYTE: - if (read_write == I2C_SMBUS_WRITE) { - chip->pointer = command; - dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, " - "wrote 0x%02x.\n", - addr, command); - } else { - data->byte = chip->words[chip->pointer++] & 0xff; - dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, " - "read 0x%02x.\n", - addr, data->byte); - } - - ret = 0; - break; - - case I2C_SMBUS_BYTE_DATA: - if (read_write == I2C_SMBUS_WRITE) { - chip->words[command] &= 0xff00; - chip->words[command] |= data->byte; - dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, " - "wrote 0x%02x at 0x%02x.\n", - addr, data->byte, command); - } else { - data->byte = chip->words[command] & 0xff; - dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, " - "read 0x%02x at 0x%02x.\n", - addr, data->byte, command); - } - chip->pointer = command + 1; - - ret = 0; - break; - - case I2C_SMBUS_WORD_DATA: - if (read_write == I2C_SMBUS_WRITE) { - chip->words[command] = data->word; - dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, " - "wrote 0x%04x at 0x%02x.\n", - addr, data->word, command); - } else { - data->word = chip->words[command]; - dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, " - "read 0x%04x at 0x%02x.\n", - addr, data->word, command); - } - - ret = 0; - break; - - case I2C_SMBUS_I2C_BLOCK_DATA: - len = data->block[0]; - if (read_write == I2C_SMBUS_WRITE) { - for (i = 0; i < len; i++) { - chip->words[command + i] &= 0xff00; - chip->words[command + i] |= data->block[1 + i]; - } - dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, " - "wrote %d bytes at 0x%02x.\n", - addr, len, command); - } else { - for (i = 0; i < len; i++) { - data->block[1 + i] = - chip->words[command + i] & 0xff; - } - dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, " - "read %d bytes at 0x%02x.\n", - addr, len, command); - } - - ret = 0; - break; - - default: - dev_dbg(&adap->dev, "Unsupported I2C/SMBus command\n"); - ret = -EOPNOTSUPP; - break; - } /* switch (size) */ - - return ret; -} - -static u32 stub_func(struct i2c_adapter *adapter) -{ - return STUB_FUNC & functionality; -} - -static const struct i2c_algorithm smbus_algorithm = { - .functionality = stub_func, - .smbus_xfer = stub_xfer, -}; - -static struct i2c_adapter stub_adapter = { - .owner = THIS_MODULE, - .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, - .algo = &smbus_algorithm, - .name = "SMBus stub driver", -}; - -static int __init i2c_stub_init(void) -{ - int i, ret; - - if (!chip_addr[0]) { - printk(KERN_ERR "i2c-stub: Please specify a chip address\n"); - return -ENODEV; - } - - for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) { - if (chip_addr[i] < 0x03 || chip_addr[i] > 0x77) { - printk(KERN_ERR "i2c-stub: Invalid chip address " - "0x%02x\n", chip_addr[i]); - return -EINVAL; - } - - printk(KERN_INFO "i2c-stub: Virtual chip at 0x%02x\n", - chip_addr[i]); - } - - /* Allocate memory for all chips at once */ - stub_chips = kzalloc(i * sizeof(struct stub_chip), GFP_KERNEL); - if (!stub_chips) { - printk(KERN_ERR "i2c-stub: Out of memory\n"); - return -ENOMEM; - } - - ret = i2c_add_adapter(&stub_adapter); - if (ret) - kfree(stub_chips); - return ret; -} - -static void __exit i2c_stub_exit(void) -{ - i2c_del_adapter(&stub_adapter); - kfree(stub_chips); -} - -MODULE_AUTHOR("Mark M. Hoffman "); -MODULE_DESCRIPTION("I2C stub driver"); -MODULE_LICENSE("GPL"); - -module_init(i2c_stub_init); -module_exit(i2c_stub_exit); - diff --git a/drivers/i2c/i2c-stub.c b/drivers/i2c/i2c-stub.c new file mode 100644 index 0000000..d0a9c59 --- /dev/null +++ b/drivers/i2c/i2c-stub.c @@ -0,0 +1,220 @@ +/* + i2c-stub.c - I2C/SMBus chip emulator + + Copyright (c) 2004 Mark M. Hoffman + Copyright (C) 2007, 2012 Jean Delvare + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#define DEBUG 1 + +#include +#include +#include +#include +#include +#include + +#define MAX_CHIPS 10 +#define STUB_FUNC (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | \ + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | \ + I2C_FUNC_SMBUS_I2C_BLOCK) + +static unsigned short chip_addr[MAX_CHIPS]; +module_param_array(chip_addr, ushort, NULL, S_IRUGO); +MODULE_PARM_DESC(chip_addr, + "Chip addresses (up to 10, between 0x03 and 0x77)"); + +static unsigned long functionality = STUB_FUNC; +module_param(functionality, ulong, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(functionality, "Override functionality bitfield"); + +struct stub_chip { + u8 pointer; + u16 words[256]; /* Byte operations use the LSB as per SMBus + specification */ +}; + +static struct stub_chip *stub_chips; + +/* Return negative errno on error. */ +static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags, + char read_write, u8 command, int size, union i2c_smbus_data *data) +{ + s32 ret; + int i, len; + struct stub_chip *chip = NULL; + + /* Search for the right chip */ + for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) { + if (addr == chip_addr[i]) { + chip = stub_chips + i; + break; + } + } + if (!chip) + return -ENODEV; + + switch (size) { + + case I2C_SMBUS_QUICK: + dev_dbg(&adap->dev, "smbus quick - addr 0x%02x\n", addr); + ret = 0; + break; + + case I2C_SMBUS_BYTE: + if (read_write == I2C_SMBUS_WRITE) { + chip->pointer = command; + dev_dbg(&adap->dev, + "smbus byte - addr 0x%02x, wrote 0x%02x.\n", + addr, command); + } else { + data->byte = chip->words[chip->pointer++] & 0xff; + dev_dbg(&adap->dev, + "smbus byte - addr 0x%02x, read 0x%02x.\n", + addr, data->byte); + } + + ret = 0; + break; + + case I2C_SMBUS_BYTE_DATA: + if (read_write == I2C_SMBUS_WRITE) { + chip->words[command] &= 0xff00; + chip->words[command] |= data->byte; + dev_dbg(&adap->dev, + "smbus byte data - addr 0x%02x, wrote 0x%02x at 0x%02x.\n", + addr, data->byte, command); + } else { + data->byte = chip->words[command] & 0xff; + dev_dbg(&adap->dev, + "smbus byte data - addr 0x%02x, read 0x%02x at 0x%02x.\n", + addr, data->byte, command); + } + chip->pointer = command + 1; + + ret = 0; + break; + + case I2C_SMBUS_WORD_DATA: + if (read_write == I2C_SMBUS_WRITE) { + chip->words[command] = data->word; + dev_dbg(&adap->dev, + "smbus word data - addr 0x%02x, wrote 0x%04x at 0x%02x.\n", + addr, data->word, command); + } else { + data->word = chip->words[command]; + dev_dbg(&adap->dev, + "smbus word data - addr 0x%02x, read 0x%04x at 0x%02x.\n", + addr, data->word, command); + } + + ret = 0; + break; + + case I2C_SMBUS_I2C_BLOCK_DATA: + len = data->block[0]; + if (read_write == I2C_SMBUS_WRITE) { + for (i = 0; i < len; i++) { + chip->words[command + i] &= 0xff00; + chip->words[command + i] |= data->block[1 + i]; + } + dev_dbg(&adap->dev, + "i2c block data - addr 0x%02x, wrote %d bytes at 0x%02x.\n", + addr, len, command); + } else { + for (i = 0; i < len; i++) { + data->block[1 + i] = + chip->words[command + i] & 0xff; + } + dev_dbg(&adap->dev, + "i2c block data - addr 0x%02x, read %d bytes at 0x%02x.\n", + addr, len, command); + } + + ret = 0; + break; + + default: + dev_dbg(&adap->dev, "Unsupported I2C/SMBus command\n"); + ret = -EOPNOTSUPP; + break; + } /* switch (size) */ + + return ret; +} + +static u32 stub_func(struct i2c_adapter *adapter) +{ + return STUB_FUNC & functionality; +} + +static const struct i2c_algorithm smbus_algorithm = { + .functionality = stub_func, + .smbus_xfer = stub_xfer, +}; + +static struct i2c_adapter stub_adapter = { + .owner = THIS_MODULE, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, + .algo = &smbus_algorithm, + .name = "SMBus stub driver", +}; + +static int __init i2c_stub_init(void) +{ + int i, ret; + + if (!chip_addr[0]) { + pr_err("i2c-stub: Please specify a chip address\n"); + return -ENODEV; + } + + for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) { + if (chip_addr[i] < 0x03 || chip_addr[i] > 0x77) { + pr_err("i2c-stub: Invalid chip address 0x%02x\n", + chip_addr[i]); + return -EINVAL; + } + + pr_info("i2c-stub: Virtual chip at 0x%02x\n", chip_addr[i]); + } + + /* Allocate memory for all chips at once */ + stub_chips = kzalloc(i * sizeof(struct stub_chip), GFP_KERNEL); + if (!stub_chips) { + pr_err("i2c-stub: Out of memory\n"); + return -ENOMEM; + } + + ret = i2c_add_adapter(&stub_adapter); + if (ret) + kfree(stub_chips); + return ret; +} + +static void __exit i2c_stub_exit(void) +{ + i2c_del_adapter(&stub_adapter); + kfree(stub_chips); +} + +MODULE_AUTHOR("Mark M. Hoffman "); +MODULE_DESCRIPTION("I2C stub driver"); +MODULE_LICENSE("GPL"); + +module_init(i2c_stub_init); +module_exit(i2c_stub_exit); -- cgit v1.1 From 79e3e5b894926d3c7b1efc69e0c5be723ceb88bd Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 28 Oct 2012 21:37:01 +0100 Subject: i2c-i801: Simplify dependency towards GPIOLIB Arbitrarily selecting GPIOLIB causes trouble on some architectures, so don't do that. Instead, just make the optional multiplexing code depend on CONFIG_I2C_MUX_GPIO instead of CONFIG_I2C_MUX for now. We can revisit if the i2c-i801 driver ever supports other multiplexing flavors. Also make that optional code depend on DMI, as it won't do anything without that. Signed-off-by: Jean Delvare Cc: Fengguang Wu --- drivers/i2c/busses/Kconfig | 1 - drivers/i2c/busses/i2c-i801.c | 9 ++++++--- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 65dd599..e9df4612 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -81,7 +81,6 @@ config I2C_I801 tristate "Intel 82801 (ICH/PCH)" depends on PCI select CHECK_SIGNATURE if X86 && DMI - select GPIOLIB if I2C_MUX help If you say yes to this option, support will be included for the Intel 801 family of mainboard I2C interfaces. Specifically, the following diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 3779315..3bc3f73 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -82,7 +82,8 @@ #include #include -#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE +#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ + defined CONFIG_DMI #include #include #include @@ -192,7 +193,8 @@ struct i801_priv { int len; u8 *data; -#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE +#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ + defined CONFIG_DMI const struct i801_mux_config *mux_drvdata; struct platform_device *mux_pdev; #endif @@ -921,7 +923,8 @@ static void __init input_apanel_init(void) {} static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) {} #endif /* CONFIG_X86 && CONFIG_DMI */ -#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE +#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ + defined CONFIG_DMI static struct i801_mux_config i801_mux_config_asus_z8_d12 = { .gpio_chip = "gpio_ich", .values = { 0x02, 0x03 }, -- cgit v1.1 From 28901f579486a69cfdf7f294a3b5a97b173fb74a Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 28 Oct 2012 21:37:01 +0100 Subject: i2c-i801: Fix comment Signed-off-by: Jean Delvare --- drivers/i2c/busses/i2c-i801.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 3bc3f73..6abc00d 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -1062,7 +1062,7 @@ static unsigned int __devinit i801_get_adapter_class(struct i801_priv *priv) id = dmi_first_match(mux_dmi_table); if (id) { - /* Remove from branch classes from trunk */ + /* Remove branch classes from trunk */ mux_config = id->driver_data; for (i = 0; i < mux_config->n_values; i++) class &= ~mux_config->classes[i]; -- cgit v1.1 From 82fa63bd6b87969dfde0139dbede243380b087d6 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 12 Oct 2012 11:55:16 +0100 Subject: i2c: mxs: remove broken PIOQUEUE support This I2C master can do DMA and PIOQUEUE (PIO with FIFO). Originally, only PIOQUEUE was supported and it had issues, then DMA support was added this cycle. The original intention was to keep PIOQUEUE since it has less overhead what is nice for small transfers. However, runtime switching between PIOQEUE and DMA depending on the transfer size never worked despite a lot of trying. Since PIOQUEUE mode itself was flaky (polling at places where interrupts failed to work) and the implementation also imposed a size limit for transfers, it is best to remove the support, so users don't fall over its limitations. It also makes the driver a lot cleaner and more robust. If somebody really wants less overhead, plain PIO mode could still be implemented with the addidtional advantage that this mode is also available on MX23, too. Signed-off-by: Wolfram Sang Reviewed-by: Marek Vasut --- drivers/i2c/busses/i2c-mxs.c | 186 ++++--------------------------------------- 1 file changed, 14 insertions(+), 172 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 1f58197..286ca19 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -1,7 +1,7 @@ /* * Freescale MXS I2C bus driver * - * Copyright (C) 2011 Wolfram Sang, Pengutronix e.K. + * Copyright (C) 2011-2012 Wolfram Sang, Pengutronix e.K. * * based on a (non-working) driver which was: * @@ -35,10 +35,6 @@ #define DRIVER_NAME "mxs-i2c" -static bool use_pioqueue; -module_param(use_pioqueue, bool, 0); -MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA"); - #define MXS_I2C_CTRL0 (0x00) #define MXS_I2C_CTRL0_SET (0x04) @@ -75,23 +71,6 @@ MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA"); MXS_I2C_CTRL1_SLAVE_STOP_IRQ | \ MXS_I2C_CTRL1_SLAVE_IRQ) -#define MXS_I2C_QUEUECTRL (0x60) -#define MXS_I2C_QUEUECTRL_SET (0x64) -#define MXS_I2C_QUEUECTRL_CLR (0x68) - -#define MXS_I2C_QUEUECTRL_QUEUE_RUN 0x20 -#define MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE 0x04 - -#define MXS_I2C_QUEUESTAT (0x70) -#define MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY 0x00002000 -#define MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK 0x0000001F - -#define MXS_I2C_QUEUECMD (0x80) - -#define MXS_I2C_QUEUEDATA (0x90) - -#define MXS_I2C_DATA (0xa0) - #define MXS_CMD_I2C_SELECT (MXS_I2C_CTRL0_RETAIN_CLOCK | \ MXS_I2C_CTRL0_PRE_SEND_START | \ @@ -153,7 +132,6 @@ struct mxs_i2c_dev { const struct mxs_i2c_speed_config *speed; /* DMA support components */ - bool dma_mode; int dma_channel; struct dma_chan *dmach; struct mxs_dma_data dma_data; @@ -172,99 +150,6 @@ static void mxs_i2c_reset(struct mxs_i2c_dev *i2c) writel(i2c->speed->timing2, i2c->regs + MXS_I2C_TIMING2); writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET); - if (i2c->dma_mode) - writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE, - i2c->regs + MXS_I2C_QUEUECTRL_CLR); - else - writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE, - i2c->regs + MXS_I2C_QUEUECTRL_SET); -} - -static void mxs_i2c_pioq_setup_read(struct mxs_i2c_dev *i2c, u8 addr, int len, - int flags) -{ - u32 data; - - writel(MXS_CMD_I2C_SELECT, i2c->regs + MXS_I2C_QUEUECMD); - - data = (addr << 1) | I2C_SMBUS_READ; - writel(data, i2c->regs + MXS_I2C_DATA); - - data = MXS_CMD_I2C_READ | MXS_I2C_CTRL0_XFER_COUNT(len) | flags; - writel(data, i2c->regs + MXS_I2C_QUEUECMD); -} - -static void mxs_i2c_pioq_setup_write(struct mxs_i2c_dev *i2c, - u8 addr, u8 *buf, int len, int flags) -{ - u32 data; - int i, shifts_left; - - data = MXS_CMD_I2C_WRITE | MXS_I2C_CTRL0_XFER_COUNT(len + 1) | flags; - writel(data, i2c->regs + MXS_I2C_QUEUECMD); - - /* - * We have to copy the slave address (u8) and buffer (arbitrary number - * of u8) into the data register (u32). To achieve that, the u8 are put - * into the MSBs of 'data' which is then shifted for the next u8. When - * appropriate, 'data' is written to MXS_I2C_DATA. So, the first u32 - * looks like this: - * - * 3 2 1 0 - * 10987654|32109876|54321098|76543210 - * --------+--------+--------+-------- - * buffer+2|buffer+1|buffer+0|slave_addr - */ - - data = ((addr << 1) | I2C_SMBUS_WRITE) << 24; - - for (i = 0; i < len; i++) { - data >>= 8; - data |= buf[i] << 24; - if ((i & 3) == 2) - writel(data, i2c->regs + MXS_I2C_DATA); - } - - /* Write out the remaining bytes if any */ - shifts_left = 24 - (i & 3) * 8; - if (shifts_left) - writel(data >> shifts_left, i2c->regs + MXS_I2C_DATA); -} - -/* - * TODO: should be replaceable with a waitqueue and RD_QUEUE_IRQ (setting the - * rd_threshold to 1). Couldn't get this to work, though. - */ -static int mxs_i2c_wait_for_data(struct mxs_i2c_dev *i2c) -{ - unsigned long timeout = jiffies + msecs_to_jiffies(1000); - - while (readl(i2c->regs + MXS_I2C_QUEUESTAT) - & MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY) { - if (time_after(jiffies, timeout)) - return -ETIMEDOUT; - cond_resched(); - } - - return 0; -} - -static int mxs_i2c_finish_read(struct mxs_i2c_dev *i2c, u8 *buf, int len) -{ - u32 uninitialized_var(data); - int i; - - for (i = 0; i < len; i++) { - if ((i & 3) == 0) { - if (mxs_i2c_wait_for_data(i2c)) - return -ETIMEDOUT; - data = readl(i2c->regs + MXS_I2C_QUEUEDATA); - } - buf[i] = data & 0xff; - data >>= 8; - } - - return 0; } static void mxs_i2c_dma_finish(struct mxs_i2c_dev *i2c) @@ -432,39 +317,17 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, init_completion(&i2c->cmd_complete); i2c->cmd_err = 0; - if (i2c->dma_mode) { - ret = mxs_i2c_dma_setup_xfer(adap, msg, flags); - if (ret) - return ret; - } else { - if (msg->flags & I2C_M_RD) { - mxs_i2c_pioq_setup_read(i2c, msg->addr, - msg->len, flags); - } else { - mxs_i2c_pioq_setup_write(i2c, msg->addr, msg->buf, - msg->len, flags); - } - - writel(MXS_I2C_QUEUECTRL_QUEUE_RUN, - i2c->regs + MXS_I2C_QUEUECTRL_SET); - } + ret = mxs_i2c_dma_setup_xfer(adap, msg, flags); + if (ret) + return ret; ret = wait_for_completion_timeout(&i2c->cmd_complete, msecs_to_jiffies(1000)); if (ret == 0) goto timeout; - if (!i2c->dma_mode && !i2c->cmd_err && (msg->flags & I2C_M_RD)) { - ret = mxs_i2c_finish_read(i2c, msg->buf, msg->len); - if (ret) - goto timeout; - } - if (i2c->cmd_err == -ENXIO) mxs_i2c_reset(i2c); - else - writel(MXS_I2C_QUEUECTRL_QUEUE_RUN, - i2c->regs + MXS_I2C_QUEUECTRL_CLR); dev_dbg(i2c->dev, "Done with err=%d\n", i2c->cmd_err); @@ -472,8 +335,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, timeout: dev_dbg(i2c->dev, "Timeout!\n"); - if (i2c->dma_mode) - mxs_i2c_dma_finish(i2c); + mxs_i2c_dma_finish(i2c); mxs_i2c_reset(i2c); return -ETIMEDOUT; } @@ -502,7 +364,6 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id) { struct mxs_i2c_dev *i2c = dev_id; u32 stat = readl(i2c->regs + MXS_I2C_CTRL1) & MXS_I2C_IRQ_MASK; - bool is_last_cmd; if (!stat) return IRQ_NONE; @@ -515,14 +376,6 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id) /* MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ is only for slaves */ i2c->cmd_err = -EIO; - if (!i2c->dma_mode) { - is_last_cmd = (readl(i2c->regs + MXS_I2C_QUEUESTAT) & - MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK) == 0; - - if (is_last_cmd || i2c->cmd_err) - complete(&i2c->cmd_complete); - } - writel(stat, i2c->regs + MXS_I2C_CTRL1_CLR); return IRQ_HANDLED; @@ -556,23 +409,14 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c) int ret; /* - * The MXS I2C DMA mode is prefered and enabled by default. - * The PIO mode is still supported, but should be used only - * for debuging purposes etc. - */ - i2c->dma_mode = !use_pioqueue; - if (!i2c->dma_mode) - dev_info(dev, "Using PIOQUEUE mode for I2C transfers!\n"); - - /* * TODO: This is a temporary solution and should be changed * to use generic DMA binding later when the helpers get in. */ ret = of_property_read_u32(node, "fsl,i2c-dma-channel", &i2c->dma_channel); if (ret) { - dev_warn(dev, "Failed to get DMA channel, using PIOQUEUE!\n"); - i2c->dma_mode = 0; + dev_err(dev, "Failed to get DMA channel!\n"); + return -ENODEV; } ret = of_property_read_u32(node, "clock-frequency", &speed); @@ -634,15 +478,13 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev) } /* Setup the DMA */ - if (i2c->dma_mode) { - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - i2c->dma_data.chan_irq = dmairq; - i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c); - if (!i2c->dmach) { - dev_err(dev, "Failed to request dma\n"); - return -ENODEV; - } + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + i2c->dma_data.chan_irq = dmairq; + i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c); + if (!i2c->dmach) { + dev_err(dev, "Failed to request dma\n"); + return -ENODEV; } platform_set_drvdata(pdev, i2c); -- cgit v1.1 From 817315f57408b1a9c78cbc7ff2bf186da45ddcc1 Mon Sep 17 00:00:00 2001 From: Philippe Begnic Date: Wed, 10 Oct 2012 13:02:26 +0200 Subject: i2c-nomadik: Fixup clock handling Make sure to clk_prepare as well as clk_enable. Signed-off-by: Philippe Begnic Signed-off-by: Ulf Hansson Signed-off-by: Linus Walleij Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-nomadik.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 698d7ac..02c3115 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -644,7 +644,11 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, pm_runtime_get_sync(&dev->adev->dev); - clk_enable(dev->clk); + status = clk_prepare_enable(dev->clk); + if (status) { + dev_err(&dev->adev->dev, "can't prepare_enable clock\n"); + goto out_clk; + } status = init_hw(dev); if (status) @@ -671,7 +675,8 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, } out: - clk_disable(dev->clk); + clk_disable_unprepare(dev->clk); +out_clk: pm_runtime_put_sync(&dev->adev->dev); dev->busy = false; -- cgit v1.1 From 91b370a0dbda5de92c2cf4c3bc0d18d6bf08f05f Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Thu, 1 Nov 2012 22:08:14 +0530 Subject: i2c: tegra: set irq name as device name When watching the irqs name of tegra i2c, all instances irq name shows as tegra_i2c. Passing the device name properly to have the irq names with instance like tegra-i2c.0, tegra-i2c.1 etc. Signed-off-by: Laxman Dewangan Acked-by: Jean Delvare Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index f981ac4..dcea77b 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -742,7 +742,7 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) } ret = devm_request_irq(&pdev->dev, i2c_dev->irq, - tegra_i2c_isr, 0, pdev->name, i2c_dev); + tegra_i2c_isr, 0, dev_name(&pdev->dev), i2c_dev); if (ret) { dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq); return ret; -- cgit v1.1 From aa1e3e81e75ceb3d977c3292cefafcd5179eb8b8 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 13 Nov 2012 22:27:19 +0100 Subject: i2c-mux-pinctrl: Fix probe error path When allocating the memory for i2c busses, the code checked the wrong variable and thus never detected if there was a memory error. Signed-off-by: Guenter Roeck Cc: stable@vger.kernel.org Signed-off-by: Jean Delvare --- drivers/i2c/muxes/i2c-mux-pinctrl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c index 5f097f3..7fa5b24 100644 --- a/drivers/i2c/muxes/i2c-mux-pinctrl.c +++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c @@ -169,7 +169,7 @@ static int __devinit i2c_mux_pinctrl_probe(struct platform_device *pdev) mux->busses = devm_kzalloc(&pdev->dev, sizeof(mux->busses) * mux->pdata->bus_count, GFP_KERNEL); - if (!mux->states) { + if (!mux->busses) { dev_err(&pdev->dev, "Cannot allocate busses\n"); ret = -ENOMEM; goto err; -- cgit v1.1