aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-arb-gpio-challenge.txt80
-rw-r--r--MAINTAINERS1
-rw-r--r--arch/arm/mach-s3c24xx/mach-rx1950.c1
-rw-r--r--arch/arm/mach-tegra/tegra.c2
-rw-r--r--arch/arm/plat-samsung/devs.c1
-rw-r--r--arch/arm/plat-samsung/include/plat/regs-iic.h56
-rw-r--r--drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c3
-rw-r--r--drivers/i2c/busses/i2c-amd756-s4882.c6
-rw-r--r--drivers/i2c/busses/i2c-at91.c58
-rw-r--r--drivers/i2c/busses/i2c-cbus-gpio.c4
-rw-r--r--drivers/i2c/busses/i2c-davinci.c77
-rw-r--r--drivers/i2c/busses/i2c-designware-core.c39
-rw-r--r--drivers/i2c/busses/i2c-designware-pcidrv.c73
-rw-r--r--drivers/i2c/busses/i2c-designware-platdrv.c83
-rw-r--r--drivers/i2c/busses/i2c-gpio.c75
-rw-r--r--drivers/i2c/busses/i2c-intel-mid.c3
-rw-r--r--drivers/i2c/busses/i2c-ismt.c2
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c5
-rw-r--r--drivers/i2c/busses/i2c-mxs.c104
-rw-r--r--drivers/i2c/busses/i2c-nforce2-s4985.c6
-rw-r--r--drivers/i2c/busses/i2c-octeon.c10
-rw-r--r--drivers/i2c/busses/i2c-powermac.c10
-rw-r--r--drivers/i2c/busses/i2c-puv3.c10
-rw-r--r--drivers/i2c/busses/i2c-pxa.c20
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c48
-rw-r--r--drivers/i2c/busses/i2c-tegra.c26
-rw-r--r--drivers/i2c/busses/i2c-viperboard.c5
-rw-r--r--drivers/i2c/busses/i2c-xiic.c6
-rw-r--r--drivers/i2c/i2c-core.c246
-rw-r--r--drivers/i2c/i2c-mux.c9
-rw-r--r--drivers/i2c/muxes/Kconfig12
-rw-r--r--drivers/i2c/muxes/Makefile2
-rw-r--r--drivers/i2c/muxes/i2c-arb-gpio-challenge.c251
-rw-r--r--drivers/i2c/muxes/i2c-mux-gpio.c17
-rw-r--r--drivers/i2c/muxes/i2c-mux-pca954x.c6
-rw-r--r--drivers/media/pci/bt8xx/bttv-i2c.c6
-rw-r--r--drivers/media/pci/mantis/mantis_i2c.c4
-rw-r--r--drivers/net/ethernet/sfc/falcon.c6
-rw-r--r--drivers/staging/media/go7007/go7007-driver.c7
-rw-r--r--include/linux/i2c-mux.h2
-rw-r--r--include/linux/i2c-tegra.h25
-rw-r--r--include/linux/i2c.h50
42 files changed, 960 insertions, 497 deletions
diff --git a/Documentation/devicetree/bindings/i2c/i2c-arb-gpio-challenge.txt b/Documentation/devicetree/bindings/i2c/i2c-arb-gpio-challenge.txt
new file mode 100644
index 00000000000..1ac8ea8ade1
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-arb-gpio-challenge.txt
@@ -0,0 +1,80 @@
+GPIO-based I2C Arbitration Using a Challenge & Response Mechanism
+=================================================================
+This uses GPIO lines and a challenge & response mechanism to arbitrate who is
+the master of an I2C bus in a multimaster situation.
+
+In many cases using GPIOs to arbitrate is not needed and a design can use
+the standard I2C multi-master rules. Using GPIOs is generally useful in
+the case where there is a device on the bus that has errata and/or bugs
+that makes standard multimaster mode not feasible.
+
+
+Algorithm:
+
+All masters on the bus have a 'bus claim' line which is an output that the
+others can see. These are all active low with pull-ups enabled. We'll
+describe these lines as:
+
+- OUR_CLAIM: output from us signaling to other hosts that we want the bus
+- THEIR_CLAIMS: output from others signaling that they want the bus
+
+The basic algorithm is to assert your line when you want the bus, then make
+sure that the other side doesn't want it also. A detailed explanation is best
+done with an example.
+
+Let's say we want to claim the bus. We:
+1. Assert OUR_CLAIM.
+2. Waits a little bit for the other sides to notice (slew time, say 10
+ microseconds).
+3. Check THEIR_CLAIMS. If none are asserted then the we have the bus and we are
+ done.
+4. Otherwise, wait for a few milliseconds and see if THEIR_CLAIMS are released.
+5. If not, back off, release the claim and wait for a few more milliseconds.
+6. Go back to 1 (until retry time has expired).
+
+
+Required properties:
+- compatible: i2c-arb-gpio-challenge
+- our-claim-gpio: The GPIO that we use to claim the bus.
+- their-claim-gpios: The GPIOs that the other sides use to claim the bus.
+ Note that some implementations may only support a single other master.
+- Standard I2C mux properties. See mux.txt in this directory.
+- Single I2C child bus node at reg 0. See mux.txt in this directory.
+
+Optional properties:
+- slew-delay-us: microseconds to wait for a GPIO to go high. Default is 10 us.
+- wait-retry-us: we'll attempt another claim after this many microseconds.
+ Default is 3000 us.
+- wait-free-us: we'll give up after this many microseconds. Default is 50000 us.
+
+
+Example:
+ i2c@12CA0000 {
+ compatible = "acme,some-i2c-device";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c-arbitrator {
+ compatible = "i2c-arb-gpio-challenge";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ i2c-parent = <&{/i2c@12CA0000}>;
+
+ our-claim-gpio = <&gpf0 3 1>;
+ their-claim-gpios = <&gpe0 4 1>;
+ slew-delay-us = <10>;
+ wait-retry-us = <3000>;
+ wait-free-us = <50000>;
+
+ i2c@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ i2c@52 {
+ // Normal I2C device
+ };
+ };
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index b57e2765a34..59d708f2924 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3919,7 +3919,6 @@ F: drivers/i2c/i2c-stub.c
I2C SUBSYSTEM
M: Wolfram Sang <wsa@the-dreams.de>
-M: "Ben Dooks (embedded platforms)" <ben-linux@fluff.org>
L: linux-i2c@vger.kernel.org
W: http://i2c.wiki.kernel.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git
diff --git a/arch/arm/mach-s3c24xx/mach-rx1950.c b/arch/arm/mach-s3c24xx/mach-rx1950.c
index 1f9ba2ae528..43f3ac5a1c7 100644
--- a/arch/arm/mach-s3c24xx/mach-rx1950.c
+++ b/arch/arm/mach-s3c24xx/mach-rx1950.c
@@ -56,7 +56,6 @@
#include <plat/cpu.h>
#include <plat/devs.h>
#include <plat/pm.h>
-#include <plat/regs-iic.h>
#include <plat/regs-serial.h>
#include "common.h"
diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
index 84deeab23ee..9cf1ab17afe 100644
--- a/arch/arm/mach-tegra/tegra.c
+++ b/arch/arm/mach-tegra/tegra.c
@@ -31,8 +31,6 @@
#include <linux/pda_power.h>
#include <linux/platform_data/tegra_usb.h>
#include <linux/io.h>
-#include <linux/i2c.h>
-#include <linux/i2c-tegra.h>
#include <linux/slab.h>
#include <linux/sys_soc.h>
#include <linux/usb/tegra_usb_phy.h>
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
index f55d3f9b508..8f456bed4fa 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -63,7 +63,6 @@
#include <linux/platform_data/usb-s3c2410_udc.h>
#include <linux/platform_data/usb-ohci-s3c2410.h>
#include <plat/usb-phy.h>
-#include <plat/regs-iic.h>
#include <plat/regs-serial.h>
#include <plat/regs-spi.h>
#include <linux/platform_data/spi-s3c64xx.h>
diff --git a/arch/arm/plat-samsung/include/plat/regs-iic.h b/arch/arm/plat-samsung/include/plat/regs-iic.h
deleted file mode 100644
index 2f7c17de8ac..00000000000
--- a/arch/arm/plat-samsung/include/plat/regs-iic.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/regs-iic.h
- *
- * Copyright (c) 2004 Simtec Electronics <linux@simtec.co.uk>
- * http://www.simtec.co.uk/products/SWLINUX/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * S3C2410 I2C Controller
-*/
-
-#ifndef __ASM_ARCH_REGS_IIC_H
-#define __ASM_ARCH_REGS_IIC_H __FILE__
-
-/* see s3c2410x user guide, v1.1, section 9 (p447) for more info */
-
-#define S3C2410_IICREG(x) (x)
-
-#define S3C2410_IICCON S3C2410_IICREG(0x00)
-#define S3C2410_IICSTAT S3C2410_IICREG(0x04)
-#define S3C2410_IICADD S3C2410_IICREG(0x08)
-#define S3C2410_IICDS S3C2410_IICREG(0x0C)
-#define S3C2440_IICLC S3C2410_IICREG(0x10)
-
-#define S3C2410_IICCON_ACKEN (1<<7)
-#define S3C2410_IICCON_TXDIV_16 (0<<6)
-#define S3C2410_IICCON_TXDIV_512 (1<<6)
-#define S3C2410_IICCON_IRQEN (1<<5)
-#define S3C2410_IICCON_IRQPEND (1<<4)
-#define S3C2410_IICCON_SCALE(x) ((x)&15)
-#define S3C2410_IICCON_SCALEMASK (0xf)
-
-#define S3C2410_IICSTAT_MASTER_RX (2<<6)
-#define S3C2410_IICSTAT_MASTER_TX (3<<6)
-#define S3C2410_IICSTAT_SLAVE_RX (0<<6)
-#define S3C2410_IICSTAT_SLAVE_TX (1<<6)
-#define S3C2410_IICSTAT_MODEMASK (3<<6)
-
-#define S3C2410_IICSTAT_START (1<<5)
-#define S3C2410_IICSTAT_BUSBUSY (1<<5)
-#define S3C2410_IICSTAT_TXRXEN (1<<4)
-#define S3C2410_IICSTAT_ARBITR (1<<3)
-#define S3C2410_IICSTAT_ASSLAVE (1<<2)
-#define S3C2410_IICSTAT_ADDR0 (1<<1)
-#define S3C2410_IICSTAT_LASTBIT (1<<0)
-
-#define S3C2410_IICLC_SDA_DELAY0 (0 << 0)
-#define S3C2410_IICLC_SDA_DELAY5 (1 << 0)
-#define S3C2410_IICLC_SDA_DELAY10 (2 << 0)
-#define S3C2410_IICLC_SDA_DELAY15 (3 << 0)
-#define S3C2410_IICLC_SDA_DELAY_MASK (3 << 0)
-
-#define S3C2410_IICLC_FILTER_ON (1<<2)
-
-#endif /* __ASM_ARCH_REGS_IIC_H */
diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c b/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c
index 88627e3ba1e..1eb86c79523 100644
--- a/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c
+++ b/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c
@@ -319,8 +319,7 @@ void oaktrail_hdmi_i2c_exit(struct pci_dev *dev)
struct hdmi_i2c_dev *i2c_dev;
hdmi_dev = pci_get_drvdata(dev);
- if (i2c_del_adapter(&oaktrail_hdmi_i2c_adapter))
- DRM_DEBUG_DRIVER("Failed to delete hdmi-i2c adapter\n");
+ i2c_del_adapter(&oaktrail_hdmi_i2c_adapter);
i2c_dev = hdmi_dev->i2c_dev;
kfree(i2c_dev);
diff --git a/drivers/i2c/busses/i2c-amd756-s4882.c b/drivers/i2c/busses/i2c-amd756-s4882.c
index 378fcb5d578..07f01ac853f 100644
--- a/drivers/i2c/busses/i2c-amd756-s4882.c
+++ b/drivers/i2c/busses/i2c-amd756-s4882.c
@@ -169,11 +169,7 @@ static int __init amd756_s4882_init(void)
}
/* Unregister physical bus */
- error = i2c_del_adapter(&amd756_smbus);
- if (error) {
- dev_err(&amd756_smbus.dev, "Physical bus removal failed\n");
- goto ERROR0;
- }
+ i2c_del_adapter(&amd756_smbus);
printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4882\n");
/* Define the 5 virtual adapters and algorithms structures */
diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
index 75195e3f5dd..6bb839b688b 100644
--- a/drivers/i2c/busses/i2c-at91.c
+++ b/drivers/i2c/busses/i2c-at91.c
@@ -603,15 +603,18 @@ static const struct of_device_id atmel_twi_dt_ids[] = {
}
};
MODULE_DEVICE_TABLE(of, atmel_twi_dt_ids);
-#else
-#define atmel_twi_dt_ids NULL
#endif
-static bool filter(struct dma_chan *chan, void *slave)
+static bool filter(struct dma_chan *chan, void *pdata)
{
- struct at_dma_slave *sl = slave;
+ struct at91_twi_pdata *sl_pdata = pdata;
+ struct at_dma_slave *sl;
+
+ if (!sl_pdata)
+ return false;
- if (sl->dma_dev == chan->device->dev) {
+ sl = &sl_pdata->dma_slave;
+ if (sl && (sl->dma_dev == chan->device->dev)) {
chan->private = sl;
return true;
} else {
@@ -622,11 +625,10 @@ static bool filter(struct dma_chan *chan, void *slave)
static int at91_twi_configure_dma(struct at91_twi_dev *dev, u32 phy_addr)
{
int ret = 0;
- struct at_dma_slave *sdata;
+ struct at91_twi_pdata *pdata = dev->pdata;
struct dma_slave_config slave_config;
struct at91_twi_dma *dma = &dev->dma;
-
- sdata = &dev->pdata->dma_slave;
+ dma_cap_mask_t mask;
memset(&slave_config, 0, sizeof(slave_config));
slave_config.src_addr = (dma_addr_t)phy_addr + AT91_TWI_RHR;
@@ -637,25 +639,22 @@ static int at91_twi_configure_dma(struct at91_twi_dev *dev, u32 phy_addr)
slave_config.dst_maxburst = 1;
slave_config.device_fc = false;
- if (sdata && sdata->dma_dev) {
- dma_cap_mask_t mask;
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
- dma->chan_tx = dma_request_channel(mask, filter, sdata);
- if (!dma->chan_tx) {
- dev_err(dev->dev, "no DMA channel available for tx\n");
- ret = -EBUSY;
- goto error;
- }
- dma->chan_rx = dma_request_channel(mask, filter, sdata);
- if (!dma->chan_rx) {
- dev_err(dev->dev, "no DMA channel available for rx\n");
- ret = -EBUSY;
- goto error;
- }
- } else {
- ret = -EINVAL;
+ dma->chan_tx = dma_request_slave_channel_compat(mask, filter, pdata,
+ dev->dev, "tx");
+ if (!dma->chan_tx) {
+ dev_err(dev->dev, "can't get a DMA channel for tx\n");
+ ret = -EBUSY;
+ goto error;
+ }
+
+ dma->chan_rx = dma_request_slave_channel_compat(mask, filter, pdata,
+ dev->dev, "rx");
+ if (!dma->chan_rx) {
+ dev_err(dev->dev, "can't get a DMA channel for rx\n");
+ ret = -EBUSY;
goto error;
}
@@ -785,12 +784,11 @@ static int at91_twi_probe(struct platform_device *pdev)
static int at91_twi_remove(struct platform_device *pdev)
{
struct at91_twi_dev *dev = platform_get_drvdata(pdev);
- int rc;
- rc = i2c_del_adapter(&dev->adapter);
+ i2c_del_adapter(&dev->adapter);
clk_disable_unprepare(dev->clk);
- return rc;
+ return 0;
}
#ifdef CONFIG_PM
@@ -828,7 +826,7 @@ static struct platform_driver at91_twi_driver = {
.driver = {
.name = "at91_i2c",
.owner = THIS_MODULE,
- .of_match_table = atmel_twi_dt_ids,
+ .of_match_table = of_match_ptr(atmel_twi_dt_ids),
.pm = at91_twi_pm_ops,
},
};
diff --git a/drivers/i2c/busses/i2c-cbus-gpio.c b/drivers/i2c/busses/i2c-cbus-gpio.c
index 98386d65931..1be13ac11dc 100644
--- a/drivers/i2c/busses/i2c-cbus-gpio.c
+++ b/drivers/i2c/busses/i2c-cbus-gpio.c
@@ -206,7 +206,9 @@ static int cbus_i2c_remove(struct platform_device *pdev)
{
struct i2c_adapter *adapter = platform_get_drvdata(pdev);
- return i2c_del_adapter(adapter);
+ i2c_del_adapter(adapter);
+
+ return 0;
}
static int cbus_i2c_probe(struct platform_device *pdev)
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index 7d1e590a7bb..cf20e06a88e 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -137,7 +137,7 @@ static inline u16 davinci_i2c_read_reg(struct davinci_i2c_dev *i2c_dev, int reg)
}
/* Generate a pulse on the i2c clock pin. */
-static void generic_i2c_clock_pulse(unsigned int scl_pin)
+static void davinci_i2c_clock_pulse(unsigned int scl_pin)
{
u16 i;
@@ -155,7 +155,7 @@ static void generic_i2c_clock_pulse(unsigned int scl_pin)
/* This routine does i2c bus recovery as specified in the
* i2c protocol Rev. 03 section 3.16 titled "Bus clear"
*/
-static void i2c_recover_bus(struct davinci_i2c_dev *dev)
+static void davinci_i2c_recover_bus(struct davinci_i2c_dev *dev)
{
u32 flag = 0;
struct davinci_i2c_platform_data *pdata = dev->pdata;
@@ -166,7 +166,7 @@ static void i2c_recover_bus(struct davinci_i2c_dev *dev)
flag |= DAVINCI_I2C_MDR_NACK;
/* write the data into mode register */
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
- generic_i2c_clock_pulse(pdata->scl_pin);
+ davinci_i2c_clock_pulse(pdata->scl_pin);
/* Send STOP */
flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
flag |= DAVINCI_I2C_MDR_STP;
@@ -289,7 +289,7 @@ static int i2c_davinci_wait_bus_not_busy(struct davinci_i2c_dev *dev,
return -ETIMEDOUT;
} else {
to_cnt = 0;
- i2c_recover_bus(dev);
+ davinci_i2c_recover_bus(dev);
i2c_davinci_init(dev);
}
}
@@ -379,7 +379,7 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
dev->adapter.timeout);
if (r == 0) {
dev_err(dev->dev, "controller timed out\n");
- i2c_recover_bus(dev);
+ davinci_i2c_recover_bus(dev);
i2c_davinci_init(dev);
dev->buf_len = 0;
return -ETIMEDOUT;
@@ -643,7 +643,7 @@ static int davinci_i2c_probe(struct platform_device *pdev)
{
struct davinci_i2c_dev *dev;
struct i2c_adapter *adap;
- struct resource *mem, *irq, *ioarea;
+ struct resource *mem, *irq;
int r;
/* NOTE: driver uses the static register mapping */
@@ -659,24 +659,18 @@ static int davinci_i2c_probe(struct platform_device *pdev)
return -ENODEV;
}
- ioarea = request_mem_region(mem->start, resource_size(mem),
- pdev->name);
- if (!ioarea) {
- dev_err(&pdev->dev, "I2C region already claimed\n");
- return -EBUSY;
- }
-
- dev = kzalloc(sizeof(struct davinci_i2c_dev), GFP_KERNEL);
+ dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_i2c_dev),
+ GFP_KERNEL);
if (!dev) {
- r = -ENOMEM;
- goto err_release_region;
+ dev_err(&pdev->dev, "Memory allocation failed\n");
+ return -ENOMEM;
}
init_completion(&dev->cmd_complete);
#ifdef CONFIG_CPU_FREQ
init_completion(&dev->xfr_complete);
#endif
- dev->dev = get_device(&pdev->dev);
+ dev->dev = &pdev->dev;
dev->irq = irq->start;
dev->pdata = dev->dev->platform_data;
platform_set_drvdata(pdev, dev);
@@ -686,10 +680,9 @@ static int davinci_i2c_probe(struct platform_device *pdev)
dev->pdata = devm_kzalloc(&pdev->dev,
sizeof(struct davinci_i2c_platform_data), GFP_KERNEL);
- if (!dev->pdata) {
- r = -ENOMEM;
- goto err_free_mem;
- }
+ if (!dev->pdata)
+ return -ENOMEM;
+
memcpy(dev->pdata, &davinci_i2c_platform_data_default,
sizeof(struct davinci_i2c_platform_data));
if (!of_property_read_u32(pdev->dev.of_node, "clock-frequency",
@@ -699,22 +692,21 @@ static int davinci_i2c_probe(struct platform_device *pdev)
dev->pdata = &davinci_i2c_platform_data_default;
}
- dev->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(dev->clk)) {
- r = -ENODEV;
- goto err_free_mem;
- }
+ dev->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(dev->clk))
+ return -ENODEV;
clk_prepare_enable(dev->clk);
- dev->base = ioremap(mem->start, resource_size(mem));
- if (!dev->base) {
- r = -EBUSY;
- goto err_mem_ioremap;
+ dev->base = devm_ioremap_resource(&pdev->dev, mem);
+ if (IS_ERR(dev->base)) {
+ r = PTR_ERR(dev->base);
+ goto err_unuse_clocks;
}
i2c_davinci_init(dev);
- r = request_irq(dev->irq, i2c_davinci_isr, 0, pdev->name, dev);
+ r = devm_request_irq(&pdev->dev, dev->irq, i2c_davinci_isr, 0,
+ pdev->name, dev);
if (r) {
dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
goto err_unuse_clocks;
@@ -723,7 +715,7 @@ static int davinci_i2c_probe(struct platform_device *pdev)
r = i2c_davinci_cpufreq_register(dev);
if (r) {
dev_err(&pdev->dev, "failed to register cpufreq\n");
- goto err_free_irq;
+ goto err_unuse_clocks;
}
adap = &dev->adapter;
@@ -740,50 +732,31 @@ static int davinci_i2c_probe(struct platform_device *pdev)
r = i2c_add_numbered_adapter(adap);
if (r) {
dev_err(&pdev->dev, "failure adding adapter\n");
- goto err_free_irq;
+ goto err_unuse_clocks;
}
of_i2c_register_devices(adap);
return 0;
-err_free_irq:
- free_irq(dev->irq, dev);
err_unuse_clocks:
- iounmap(dev->base);
-err_mem_ioremap:
clk_disable_unprepare(dev->clk);
- clk_put(dev->clk);
dev->clk = NULL;
-err_free_mem:
- put_device(&pdev->dev);
- kfree(dev);
-err_release_region:
- release_mem_region(mem->start, resource_size(mem));
-
return r;
}
static int davinci_i2c_remove(struct platform_device *pdev)
{
struct davinci_i2c_dev *dev = platform_get_drvdata(pdev);
- struct resource *mem;
i2c_davinci_cpufreq_deregister(dev);
i2c_del_adapter(&dev->adapter);
- put_device(&pdev->dev);
clk_disable_unprepare(dev->clk);
- clk_put(dev->clk);
dev->clk = NULL;
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, 0);
- free_irq(dev->irq, dev);
- iounmap(dev->base);
- kfree(dev);
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(mem->start, resource_size(mem));
return 0;
}
diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c
index 94fd8187540..21fbb340ad6 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -68,6 +68,7 @@
#define DW_IC_TXFLR 0x74
#define DW_IC_RXFLR 0x78
#define DW_IC_TX_ABRT_SOURCE 0x80
+#define DW_IC_ENABLE_STATUS 0x9c
#define DW_IC_COMP_PARAM_1 0xf4
#define DW_IC_COMP_TYPE 0xfc
#define DW_IC_COMP_TYPE_VALUE 0x44570140
@@ -248,6 +249,27 @@ static u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
return ((ic_clk * (tLOW + tf) + 5000) / 10000) - 1 + offset;
}
+static void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable)
+{
+ int timeout = 100;
+
+ do {
+ dw_writel(dev, enable, DW_IC_ENABLE);
+ if ((dw_readl(dev, DW_IC_ENABLE_STATUS) & 1) == enable)
+ return;
+
+ /*
+ * Wait 10 times the signaling period of the highest I2C
+ * transfer supported by the driver (for 400KHz this is
+ * 25us) as described in the DesignWare I2C databook.
+ */
+ usleep_range(25, 250);
+ } while (timeout--);
+
+ dev_warn(dev->dev, "timeout in %sabling adapter\n",
+ enable ? "en" : "dis");
+}
+
/**
* i2c_dw_init() - initialize the designware i2c master hardware
* @dev: device private data
@@ -278,7 +300,7 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
}
/* Disable the adapter */
- dw_writel(dev, 0, DW_IC_ENABLE);
+ __i2c_dw_enable(dev, false);
/* set standard and fast speed deviders for high/low periods */
@@ -333,7 +355,7 @@ static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
return -ETIMEDOUT;
}
timeout--;
- mdelay(1);
+ usleep_range(1000, 1100);
}
return 0;
@@ -345,7 +367,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
u32 ic_con;
/* Disable the adapter */
- dw_writel(dev, 0, DW_IC_ENABLE);
+ __i2c_dw_enable(dev, false);
/* set the slave (target) address */
dw_writel(dev, msgs[dev->msg_write_idx].addr, DW_IC_TAR);
@@ -359,7 +381,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
dw_writel(dev, ic_con, DW_IC_CON);
/* Enable the adapter */
- dw_writel(dev, 1, DW_IC_ENABLE);
+ __i2c_dw_enable(dev, true);
/* Enable interrupts */
dw_writel(dev, DW_IC_INTR_DEFAULT_MASK, DW_IC_INTR_MASK);
@@ -565,7 +587,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
/* no error */
if (likely(!dev->cmd_err)) {
/* Disable the adapter */
- dw_writel(dev, 0, DW_IC_ENABLE);
+ __i2c_dw_enable(dev, false);
ret = num;
goto done;
}
@@ -578,7 +600,8 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
ret = -EIO;
done:
- pm_runtime_put(dev->dev);
+ pm_runtime_mark_last_busy(dev->dev);
+ pm_runtime_put_autosuspend(dev->dev);
mutex_unlock(&dev->lock);
return ret;
@@ -700,7 +723,7 @@ EXPORT_SYMBOL_GPL(i2c_dw_isr);
void i2c_dw_enable(struct dw_i2c_dev *dev)
{
/* Enable the adapter */
- dw_writel(dev, 1, DW_IC_ENABLE);
+ __i2c_dw_enable(dev, true);
}
EXPORT_SYMBOL_GPL(i2c_dw_enable);
@@ -713,7 +736,7 @@ EXPORT_SYMBOL_GPL(i2c_dw_is_enabled);
void i2c_dw_disable(struct dw_i2c_dev *dev)
{
/* Disable controller */
- dw_writel(dev, 0, DW_IC_ENABLE);
+ __i2c_dw_enable(dev, false);
/* Disable all interupts */
dw_writel(dev, 0, DW_IC_INTR_MASK);
diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c
index 7c5e383c350..f6ed06c966e 100644
--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
+++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
@@ -208,68 +208,45 @@ static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
}
static int i2c_dw_pci_probe(struct pci_dev *pdev,
-const struct pci_device_id *id)
+ const struct pci_device_id *id)
{
struct dw_i2c_dev *dev;
struct i2c_adapter *adap;
- unsigned long start, len;
- void __iomem *base;
int r;
struct dw_pci_controller *controller;
if (id->driver_data >= ARRAY_SIZE(dw_pci_controllers)) {
- printk(KERN_ERR "dw_i2c_pci_probe: invalid driver data %ld\n",
+ dev_err(&pdev->dev, "%s: invalid driver data %ld\n", __func__,
id->driver_data);
return -EINVAL;
}
controller = &dw_pci_controllers[id->driver_data];
- r = pci_enable_device(pdev);
+ r = pcim_enable_device(pdev);
if (r) {
dev_err(&pdev->dev, "Failed to enable I2C PCI device (%d)\n",
r);
- goto exit;
+ return r;
}
- /* Determine the address of the I2C area */
- start = pci_resource_start(pdev, 0);
- len = pci_resource_len(pdev, 0);
- if (!start || len == 0) {
- dev_err(&pdev->dev, "base address not set\n");
- r = -ENODEV;
- goto exit;
- }
-
- r = pci_request_region(pdev, 0, DRIVER_NAME);
+ r = pcim_iomap_regions(pdev, 1 << 0, pci_name(pdev));
if (r) {
- dev_err(&pdev->dev, "failed to request I2C region "
- "0x%lx-0x%lx\n", start,
- (unsigned long)pci_resource_end(pdev, 0));
- goto exit;
- }
-
- base = ioremap_nocache(start, len);
- if (!base) {
dev_err(&pdev->dev, "I/O memory remapping failed\n");
- r = -ENOMEM;
- goto err_release_region;
+ return r;
}
-
- dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL);
- if (!dev) {
- r = -ENOMEM;
- goto err_release_region;
- }
+ dev = devm_kzalloc(&pdev->dev, sizeof(struct dw_i2c_dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
init_completion(&dev->cmd_complete);
mutex_init(&dev->lock);
dev->clk = NULL;
dev->controller = controller;
dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
- dev->base = base;
- dev->dev = get_device(&pdev->dev);
+ dev->base = pcim_iomap_table(pdev)[0];
+ dev->dev = &pdev->dev;
dev->functionality =
I2C_FUNC_I2C |
I2C_FUNC_SMBUS_BYTE |
@@ -284,7 +261,7 @@ const struct pci_device_id *id)
dev->rx_fifo_depth = controller->rx_fifo_depth;
r = i2c_dw_init(dev);
if (r)
- goto err_iounmap;
+ return r;
<