diff options
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/Kconfig | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-amd756.c | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-omap.c | 36 | ||||
-rw-r--r-- | drivers/i2c/chips/Makefile | 7 | ||||
-rw-r--r-- | drivers/i2c/i2c-core.c | 10 |
5 files changed, 44 insertions, 13 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 476b0bb72d6..5fa9c3c67e0 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -100,7 +100,7 @@ config I2C_AU1550 config I2C_BLACKFIN_TWI tristate "Blackfin TWI I2C support" - depends on BF534 || BF536 || BF537 || BF54x + depends on BF534 || BF536 || BF537 help This is the TWI I2C device driver for Blackfin 534/536/537/54x. This driver can also be built as a module. If so, the module diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c index 573abe44084..2fa43183d37 100644 --- a/drivers/i2c/busses/i2c-amd756.c +++ b/drivers/i2c/busses/i2c-amd756.c @@ -335,7 +335,7 @@ static int __devinit amd756_probe(struct pci_dev *pdev, u8 temp; /* driver_data might come from user-space, so check it */ - if (id->driver_data > ARRAY_SIZE(chipname)) + if (id->driver_data >= ARRAY_SIZE(chipname)) return -EINVAL; if (amd756_ioport) { diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index da6639707ea..7ba31770d77 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -128,6 +128,8 @@ struct omap_i2c_dev { size_t buf_len; struct i2c_adapter adapter; unsigned rev1:1; + unsigned idle:1; + u16 iestate; /* Saved interrupt register */ }; static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev, @@ -174,18 +176,30 @@ static void omap_i2c_put_clocks(struct omap_i2c_dev *dev) } } -static void omap_i2c_enable_clocks(struct omap_i2c_dev *dev) +static void omap_i2c_unidle(struct omap_i2c_dev *dev) { if (dev->iclk != NULL) clk_enable(dev->iclk); clk_enable(dev->fclk); + if (dev->iestate) + omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate); + dev->idle = 0; } -static void omap_i2c_disable_clocks(struct omap_i2c_dev *dev) +static void omap_i2c_idle(struct omap_i2c_dev *dev) { + u16 iv; + + dev->idle = 1; + dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); + omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0); + if (dev->rev1) + iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */ + else + omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, dev->iestate); + clk_disable(dev->fclk); if (dev->iclk != NULL) clk_disable(dev->iclk); - clk_disable(dev->fclk); } static int omap_i2c_init(struct omap_i2c_dev *dev) @@ -360,7 +374,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) int i; int r; - omap_i2c_enable_clocks(dev); + omap_i2c_unidle(dev); if ((r = omap_i2c_wait_for_bb(dev)) < 0) goto out; @@ -374,7 +388,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) if (r == 0) r = num; out: - omap_i2c_disable_clocks(dev); + omap_i2c_idle(dev); return r; } @@ -403,6 +417,9 @@ omap_i2c_rev1_isr(int this_irq, void *dev_id) struct omap_i2c_dev *dev = dev_id; u16 iv, w; + if (dev->idle) + return IRQ_NONE; + iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); switch (iv) { case 0x00: /* None */ @@ -457,6 +474,9 @@ omap_i2c_isr(int this_irq, void *dev_id) u16 stat, w; int count = 0; + if (dev->idle) + return IRQ_NONE; + bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); while ((stat = (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG))) & bits) { dev_dbg(dev->dev, "IRQ (ISR = 0x%04x)\n", stat); @@ -575,7 +595,7 @@ omap_i2c_probe(struct platform_device *pdev) if ((r = omap_i2c_get_clocks(dev)) != 0) goto err_free_mem; - omap_i2c_enable_clocks(dev); + omap_i2c_unidle(dev); if (cpu_is_omap15xx()) dev->rev1 = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) < 0x20; @@ -610,7 +630,7 @@ omap_i2c_probe(struct platform_device *pdev) goto err_free_irq; } - omap_i2c_disable_clocks(dev); + omap_i2c_idle(dev); return 0; @@ -618,7 +638,7 @@ err_free_irq: free_irq(dev->irq, dev); err_unuse_clocks: omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); - omap_i2c_disable_clocks(dev); + omap_i2c_idle(dev); omap_i2c_put_clocks(dev); err_free_mem: platform_set_drvdata(pdev, NULL); diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile index 501f00cea78..e47aca0ca5a 100644 --- a/drivers/i2c/chips/Makefile +++ b/drivers/i2c/chips/Makefile @@ -1,6 +1,13 @@ # # Makefile for miscellaneous I2C chip drivers. # +# Think twice before you add a new driver to this directory. +# Device drivers are better grouped according to the functionality they +# implement rather than to the bus they are connected to. In particular: +# * Hardware monitoring chip drivers go to drivers/hwmon +# * RTC chip drivers go to drivers/rtc +# * I/O expander drivers go to drivers/gpio +# obj-$(CONFIG_DS1682) += ds1682.o obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 96da22e9a5a..8b645c6b2cb 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -90,12 +90,16 @@ static int i2c_device_probe(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct i2c_driver *driver = to_i2c_driver(dev->driver); + int status; if (!driver->probe) return -ENODEV; client->driver = driver; dev_dbg(dev, "probe\n"); - return driver->probe(client); + status = driver->probe(client); + if (status) + client->driver = NULL; + return status; } static int i2c_device_remove(struct device *dev) @@ -485,8 +489,8 @@ EXPORT_SYMBOL(i2c_add_adapter); * Context: can sleep * * This routine is used to declare an I2C adapter when its bus number - * matters. Example: for I2C adapters from system-on-chip CPUs, or - * otherwise built in to the system's mainboard, and where i2c_board_info + * matters. For example, use it for I2C adapters from system-on-chip CPUs, + * or otherwise built in to the system's mainboard, and where i2c_board_info * is used to properly configure I2C devices. * * If no devices have pre-been declared for this bus, then be sure to |