diff options
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/algos/i2c-algo-bit.c | 24 | ||||
-rw-r--r-- | drivers/i2c/algos/i2c-algo-pca.c | 6 | ||||
-rw-r--r-- | drivers/i2c/busses/Kconfig | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-designware.c | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-ixp2000.c | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-nomadik.c | 9 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-omap.c | 29 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-pxa-pci.c | 5 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-tegra.c | 60 | ||||
-rw-r--r-- | drivers/i2c/busses/scx200_acb.c | 6 |
10 files changed, 77 insertions, 68 deletions
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c index d6d58684712b..85584a547c25 100644 --- a/drivers/i2c/algos/i2c-algo-bit.c +++ b/drivers/i2c/algos/i2c-algo-bit.c @@ -47,8 +47,8 @@ /* ----- global variables --------------------------------------------- */ static int bit_test; /* see if the line-setting functions work */ -module_param(bit_test, bool, 0); -MODULE_PARM_DESC(bit_test, "Test the lines of the bus to see if it is stuck"); +module_param(bit_test, int, S_IRUGO); +MODULE_PARM_DESC(bit_test, "lines testing - 0 off; 1 report; 2 fail if stuck"); #ifdef DEBUG static int i2c_debug = 1; @@ -250,7 +250,9 @@ static int test_bus(struct i2c_adapter *i2c_adap) sda = getsda(adap); scl = (adap->getscl == NULL) ? 1 : getscl(adap); if (!scl || !sda) { - printk(KERN_WARNING "%s: bus seems to be busy\n", name); + printk(KERN_WARNING + "%s: bus seems to be busy (scl=%d, sda=%d)\n", + name, scl, sda); goto bailout; } @@ -441,7 +443,7 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) acknak(i2c_adap, 0); dev_err(&i2c_adap->dev, "readbytes: invalid " "block length (%d)\n", inval); - return -EREMOTEIO; + return -EPROTO; } /* The original count value accounts for the extra bytes, that is, either 1 for a regular transaction, @@ -470,7 +472,7 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) * reads, writes as well as 10bit-addresses. * returns: * 0 everything went okay, the chip ack'ed, or IGNORE_NAK flag was set - * -x an error occurred (like: -EREMOTEIO if the device did not answer, or + * -x an error occurred (like: -ENXIO if the device did not answer, or * -ETIMEDOUT, for example if the lines are stuck...) */ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) @@ -493,14 +495,14 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) if ((ret != 1) && !nak_ok) { dev_err(&i2c_adap->dev, "died at extended address code\n"); - return -EREMOTEIO; + return -ENXIO; } /* the remaining 8 bit address */ ret = i2c_outb(i2c_adap, msg->addr & 0x7f); if ((ret != 1) && !nak_ok) { /* the chip did not ack / xmission error occurred */ dev_err(&i2c_adap->dev, "died at 2nd address code\n"); - return -EREMOTEIO; + return -ENXIO; } if (flags & I2C_M_RD) { bit_dbg(3, &i2c_adap->dev, "emitting repeated " @@ -512,7 +514,7 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) if ((ret != 1) && !nak_ok) { dev_err(&i2c_adap->dev, "died at repeated address code\n"); - return -EREMOTEIO; + return -EIO; } } } else { /* normal 7bit address */ @@ -570,7 +572,7 @@ static int bit_xfer(struct i2c_adapter *i2c_adap, ret, ret == 1 ? "" : "s"); if (ret < pmsg->len) { if (ret >= 0) - ret = -EREMOTEIO; + ret = -EIO; goto bailout; } } else { @@ -581,7 +583,7 @@ static int bit_xfer(struct i2c_adapter *i2c_adap, ret, ret == 1 ? "" : "s"); if (ret < pmsg->len) { if (ret >= 0) - ret = -EREMOTEIO; + ret = -EIO; goto bailout; } } @@ -624,7 +626,7 @@ static int __i2c_bit_add_bus(struct i2c_adapter *adap, if (bit_test) { ret = test_bus(adap); - if (ret < 0) + if (bit_test >= 2 && ret < 0) return -ENODEV; } diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c index 4ca9cf9cde73..beb9ffe2564b 100644 --- a/drivers/i2c/algos/i2c-algo-pca.c +++ b/drivers/i2c/algos/i2c-algo-pca.c @@ -196,7 +196,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap, } else { dev_dbg(&i2c_adap->dev, "bus is not idle. status is " "%#04x\n", state); - return -EAGAIN; + return -EBUSY; } } @@ -224,7 +224,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap, } curmsg = 0; - ret = -EREMOTEIO; + ret = -EIO; while (curmsg < num) { state = pca_status(adap); @@ -259,6 +259,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap, case 0x20: /* SLA+W has been transmitted; NOT ACK has been received */ DEB2("NOT ACK received after SLA+W\n"); pca_stop(adap); + ret = -ENXIO; goto out; case 0x40: /* SLA+R has been transmitted; ACK has been received */ @@ -283,6 +284,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap, case 0x48: /* SLA+R has been transmitted; NOT ACK has been received */ DEB2("NOT ACK received after SLA+R\n"); pca_stop(adap); + ret = -ENXIO; goto out; case 0x30: /* Data byte in I2CDAT has been transmitted; NOT ACK has been received */ diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 646068e5100b..d1fc5cf9aa4d 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -789,7 +789,7 @@ config I2C_ACORN config I2C_ELEKTOR tristate "Elektor ISA card" - depends on ISA && BROKEN_ON_SMP + depends on ISA && HAS_IOPORT && BROKEN_ON_SMP select I2C_ALGOPCF help This supports the PCF8584 ISA bus I2C adapter. Say Y if you own diff --git a/drivers/i2c/busses/i2c-designware.c b/drivers/i2c/busses/i2c-designware.c index b7a51c43b185..1b42b50b5992 100644 --- a/drivers/i2c/busses/i2c-designware.c +++ b/drivers/i2c/busses/i2c-designware.c @@ -390,7 +390,7 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev) int tx_limit, rx_limit; u32 addr = msgs[dev->msg_write_idx].addr; u32 buf_len = dev->tx_buf_len; - u8 *buf = dev->tx_buf;; + u8 *buf = dev->tx_buf; intr_mask = DW_IC_INTR_DEFAULT_MASK; diff --git a/drivers/i2c/busses/i2c-ixp2000.c b/drivers/i2c/busses/i2c-ixp2000.c index 5d8aed5ec21b..c01e9519f6c1 100644 --- a/drivers/i2c/busses/i2c-ixp2000.c +++ b/drivers/i2c/busses/i2c-ixp2000.c @@ -35,7 +35,7 @@ #include <linux/slab.h> #include <mach/hardware.h> /* Pick up IXP2000-specific bits */ -#include <mach/gpio.h> +#include <mach/gpio-ixp2000.h> static inline int ixp2000_scl_pin(void *data) { diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 0c731ca69f15..b228e09c5d05 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -146,6 +146,7 @@ struct i2c_nmk_client { * @stop: stop condition * @xfer_complete: acknowledge completion for a I2C message * @result: controller propogated result + * @regulator: pointer to i2c regulator * @busy: Busy doing transfer */ struct nmk_i2c_dev { @@ -417,12 +418,12 @@ static int read_i2c(struct nmk_i2c_dev *dev) writel(readl(dev->virtbase + I2C_IMSCR) | irq_mask, dev->virtbase + I2C_IMSCR); - timeout = wait_for_completion_interruptible_timeout( + timeout = wait_for_completion_timeout( &dev->xfer_complete, dev->adap.timeout); if (timeout < 0) { dev_err(&dev->pdev->dev, - "wait_for_completion_interruptible_timeout" + "wait_for_completion_timeout" "returned %d waiting for event\n", timeout); status = timeout; } @@ -504,12 +505,12 @@ static int write_i2c(struct nmk_i2c_dev *dev) writel(readl(dev->virtbase + I2C_IMSCR) | irq_mask, dev->virtbase + I2C_IMSCR); - timeout = wait_for_completion_interruptible_timeout( + timeout = wait_for_completion_timeout( &dev->xfer_complete, dev->adap.timeout); if (timeout < 0) { dev_err(&dev->pdev->dev, - "wait_for_completion_interruptible_timeout" + "wait_for_completion_timeout " "returned %d waiting for event\n", timeout); status = timeout; } diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 1a766cf74f6b..2dfb63176856 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1139,41 +1139,12 @@ omap_i2c_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_SUSPEND -static int omap_i2c_suspend(struct device *dev) -{ - if (!pm_runtime_suspended(dev)) - if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend) - dev->bus->pm->runtime_suspend(dev); - - return 0; -} - -static int omap_i2c_resume(struct device *dev) -{ - if (!pm_runtime_suspended(dev)) - if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_resume) - dev->bus->pm->runtime_resume(dev); - - return 0; -} - -static struct dev_pm_ops omap_i2c_pm_ops = { - .suspend = omap_i2c_suspend, - .resume = omap_i2c_resume, -}; -#define OMAP_I2C_PM_OPS (&omap_i2c_pm_ops) -#else -#define OMAP_I2C_PM_OPS NULL -#endif - static struct platform_driver omap_i2c_driver = { .probe = omap_i2c_probe, .remove = omap_i2c_remove, .driver = { .name = "omap_i2c", .owner = THIS_MODULE, - .pm = OMAP_I2C_PM_OPS, }, }; diff --git a/drivers/i2c/busses/i2c-pxa-pci.c b/drivers/i2c/busses/i2c-pxa-pci.c index 6659d269b841..b73da6cd6f91 100644 --- a/drivers/i2c/busses/i2c-pxa-pci.c +++ b/drivers/i2c/busses/i2c-pxa-pci.c @@ -109,12 +109,15 @@ static int __devinit ce4100_i2c_probe(struct pci_dev *dev, return -EINVAL; } sds = kzalloc(sizeof(*sds), GFP_KERNEL); - if (!sds) + if (!sds) { + ret = -ENOMEM; goto err_mem; + } for (i = 0; i < ARRAY_SIZE(sds->pdev); i++) { sds->pdev[i] = add_i2c_device(dev, i); if (IS_ERR(sds->pdev[i])) { + ret = PTR_ERR(sds->pdev[i]); while (--i >= 0) platform_device_unregister(sds->pdev[i]); goto err_dev_add; diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 2440b7411978..3c94c4a81a55 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -270,14 +270,30 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev) /* Rounds down to not include partial word at the end of buf */ words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD; - if (words_to_transfer > tx_fifo_avail) - words_to_transfer = tx_fifo_avail; - i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer); - - buf += words_to_transfer * BYTES_PER_FIFO_WORD; - buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD; - tx_fifo_avail -= words_to_transfer; + /* It's very common to have < 4 bytes, so optimize that case. */ + if (words_to_transfer) { + if (words_to_transfer > tx_fifo_avail) + words_to_transfer = tx_fifo_avail; + + /* + * Update state before writing to FIFO. If this casues us + * to finish writing all bytes (AKA buf_remaining goes to 0) we + * have a potential for an interrupt (PACKET_XFER_COMPLETE is + * not maskable). We need to make sure that the isr sees + * buf_remaining as 0 and doesn't call us back re-entrantly. + */ + buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD; + tx_fifo_avail -= words_to_transfer; + i2c_dev->msg_buf_remaining = buf_remaining; + i2c_dev->msg_buf = buf + + words_to_transfer * BYTES_PER_FIFO_WORD; + barrier(); + + i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer); + + buf += words_to_transfer * BYTES_PER_FIFO_WORD; + } /* * If there is a partial word at the end of buf, handle it manually to @@ -287,14 +303,15 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev) if (tx_fifo_avail > 0 && buf_remaining > 0) { BUG_ON(buf_remaining > 3); memcpy(&val, buf, buf_remaining); + + /* Again update before writing to FIFO to make sure isr sees. */ + i2c_dev->msg_buf_remaining = 0; + i2c_dev->msg_buf = NULL; + barrier(); + i2c_writel(i2c_dev, val, I2C_TX_FIFO); - buf_remaining = 0; - tx_fifo_avail--; } - BUG_ON(tx_fifo_avail > 0 && buf_remaining > 0); - i2c_dev->msg_buf_remaining = buf_remaining; - i2c_dev->msg_buf = buf; return 0; } @@ -411,9 +428,10 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) tegra_i2c_mask_irq(i2c_dev, I2C_INT_TX_FIFO_DATA_REQ); } - if ((status & I2C_INT_PACKET_XFER_COMPLETE) && - !i2c_dev->msg_buf_remaining) + if (status & I2C_INT_PACKET_XFER_COMPLETE) { + BUG_ON(i2c_dev->msg_buf_remaining); complete(&i2c_dev->msg_complete); + } i2c_writel(i2c_dev, status, I2C_INT_STATUS); if (i2c_dev->is_dvc) @@ -531,7 +549,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], static u32 tegra_i2c_func(struct i2c_adapter *adap) { - return I2C_FUNC_I2C; + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; } static const struct i2c_algorithm tegra_i2c_algo = { @@ -719,6 +737,17 @@ static int tegra_i2c_resume(struct platform_device *pdev) } #endif +#if defined(CONFIG_OF) +/* Match table for of_platform binding */ +static const struct of_device_id tegra_i2c_of_match[] __devinitconst = { + { .compatible = "nvidia,tegra20-i2c", }, + {}, +}; +MODULE_DEVICE_TABLE(of, tegra_i2c_of_match); +#else +#define tegra_i2c_of_match NULL +#endif + static struct platform_driver tegra_i2c_driver = { .probe = tegra_i2c_probe, .remove = tegra_i2c_remove, @@ -729,6 +758,7 @@ static struct platform_driver tegra_i2c_driver = { .driver = { .name = "tegra-i2c", .owner = THIS_MODULE, + .of_match_table = tegra_i2c_of_match, }, }; diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index 986e5f62debe..91e349c884c5 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -550,7 +550,7 @@ static int __devexit scx200_remove(struct platform_device *pdev) return 0; } -static struct platform_driver scx200_pci_drv = { +static struct platform_driver scx200_pci_driver = { .driver = { .name = "cs5535-smb", .owner = THIS_MODULE, @@ -593,14 +593,14 @@ static int __init scx200_acb_init(void) return 0; /* No ISA devices; register the platform driver for PCI-based devices */ - return platform_driver_register(&scx200_pci_drv); + return platform_driver_register(&scx200_pci_driver); } static void __exit scx200_acb_cleanup(void) { struct scx200_acb_iface *iface; - platform_driver_unregister(&scx200_pci_drv); + platform_driver_unregister(&scx200_pci_driver); mutex_lock(&scx200_acb_list_mutex); while ((iface = scx200_acb_list) != NULL) { |