From 82b20d8bae03406e954d8b7d0f6f734967088b17 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 2 Aug 2010 07:16:37 +0000 Subject: i2c: i2c-sh_mobile irq rollback fix Update the i2c-sh_mobile driver to properly free interrupts. The function sh_mobile_i2c_hook_irqs() is fixed so module both unload and load are working as expected. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/i2c/busses/i2c-sh_mobile.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index ffb405d7c6f2..97b84b80d0ff 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -497,15 +497,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++; } @@ -513,16 +515,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; -- cgit v1.2.3 From cc33e54290ed845904dac4b047934207738f0205 Mon Sep 17 00:00:00 2001 From: Bernhard Walle Date: Mon, 27 Sep 2010 12:55:16 +0200 Subject: i2c-octeon: Return -ETIMEDOUT in octeon_i2c_wait() on timeout It doesn't make sense to set result to -ETIMEDOUT but return 0 (success) afterwards. Since there's code in octeon_i2c_start() to handle the error, it should be called. Signed-off-by: Bernhard Walle Acked-by: David Daney Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-octeon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c index 0e9f85d0a835..56dbe54e8811 100644 --- a/drivers/i2c/busses/i2c-octeon.c +++ b/drivers/i2c/busses/i2c-octeon.c @@ -218,7 +218,7 @@ static int octeon_i2c_wait(struct octeon_i2c *i2c) return result; } else if (result == 0) { dev_dbg(i2c->dev, "%s: timeout\n", __func__); - result = -ETIMEDOUT; + return -ETIMEDOUT; } return 0; -- cgit v1.2.3 From 4bba0fd8d1c6d405df666e2573e1a1f917098be0 Mon Sep 17 00:00:00 2001 From: Jon Povey Date: Fri, 17 Sep 2010 12:02:11 +0900 Subject: i2c-davinci: Fix race when setting up for TX When setting up to transmit, a race exists between the ISR and i2c_davinci_xfer_msg() trying to load the first byte and adjust counters. This is mostly visible for transmits > 1 byte long. The hardware starts sending immediately that MDR is loaded. IMR trickery doesn't work because if we start sending, finish the first byte and an XRDY event occurs before we load IMR to unmask it, we never get an interrupt, and we timeout. Move the MDR load after DXR,IMR loads to avoid this race without locking. Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985 Signed-off-by: Jon Povey Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-davinci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 2222c87876b9..b8feac5f2ef4 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -357,9 +357,6 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) dev->terminate = 0; - /* write the data into mode register */ - davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); - /* * First byte should be set here, not after interrupt, * because transmit-data-ready interrupt can come before @@ -371,6 +368,9 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) dev->buf_len--; } + /* write the data into mode register; start transmitting */ + davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); + r = wait_for_completion_interruptible_timeout(&dev->cmd_complete, dev->adapter.timeout); if (r == 0) { -- cgit v1.2.3 From 753419f59e10d7181e43f0b9cc5beff43ef3f7a4 Mon Sep 17 00:00:00 2001 From: Vishwanath BS Date: Thu, 30 Sep 2010 14:14:22 +0200 Subject: i2c: Fix for suspend/resume issue In current i2c core driver, call to pm_runtime_set_active from i2c_device_pm_resume will unconditionally enable i2c module and increment child count of the parent. Because of this, in CPU Idle path, i2c does not idle, preventing Core to enter retention. Also i2c module will not be suspended upon system suspend as pm_runtime_set_suspended is not called from i2c_device_pm_suspend. This issue is fixed by removing pm_runtime_set_active call from resume path which is not necessary. This fix has been tested on OMAP4430. Signed-off-by: Partha Basak Signed-off-by: Vishwanath BS Acked-by: Rafael J. Wysocki Cc: Kevin Hilman Cc: Ben Dooks Signed-off-by: Jean Delvare --- drivers/i2c/i2c-core.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 6649176de940..13927d54cb4e 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -216,12 +216,6 @@ static int i2c_device_pm_resume(struct device *dev) else ret = i2c_legacy_resume(dev); - if (!ret) { - pm_runtime_disable(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - } - return ret; } -- cgit v1.2.3 From 6abb930af064fb1cf4177d32e2c7bfb89eee0fe5 Mon Sep 17 00:00:00 2001 From: Yegor Yefremov Date: Thu, 30 Sep 2010 14:14:22 +0200 Subject: i2c-pca: Fix waitforcompletion() return value ret is still -1, if during the polling read_byte() returns at once with I2C_PCA_CON_SI set. So ret > 0 would lead *_waitforcompletion() to return 0, in spite of the proper behavior. The routine was rewritten, so that ret has always a proper value, before returning. Signed-off-by: Yegor Yefremov Reviewed-by: Wolfram Sang Cc: stable@kernel.org Signed-off-by: Jean Delvare --- drivers/i2c/busses/i2c-pca-isa.c | 12 ++++++++---- drivers/i2c/busses/i2c-pca-platform.c | 11 +++++++---- 2 files changed, 15 insertions(+), 8 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c index bbd77603a417..29933f87d8fa 100644 --- a/drivers/i2c/busses/i2c-pca-isa.c +++ b/drivers/i2c/busses/i2c-pca-isa.c @@ -71,8 +71,8 @@ static int pca_isa_readbyte(void *pd, int reg) static int pca_isa_waitforcompletion(void *pd) { - long ret = ~0; unsigned long timeout; + long ret; if (irq > -1) { ret = wait_event_timeout(pca_wait, @@ -81,11 +81,15 @@ static int pca_isa_waitforcompletion(void *pd) } else { /* Do polling */ timeout = jiffies + pca_isa_ops.timeout; - while (((pca_isa_readbyte(pd, I2C_PCA_CON) - & I2C_PCA_CON_SI) == 0) - && (ret = time_before(jiffies, timeout))) + do { + ret = time_before(jiffies, timeout); + if (pca_isa_readbyte(pd, I2C_PCA_CON) + & I2C_PCA_CON_SI) + break; udelay(100); + } while (ret); } + return ret > 0; } diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c index ef5c78487eb7..5f6d7f89e225 100644 --- a/drivers/i2c/busses/i2c-pca-platform.c +++ b/drivers/i2c/busses/i2c-pca-platform.c @@ -80,8 +80,8 @@ static void i2c_pca_pf_writebyte32(void *pd, int reg, int val) static int i2c_pca_pf_waitforcompletion(void *pd) { struct i2c_pca_pf_data *i2c = pd; - long ret = ~0; unsigned long timeout; + long ret; if (i2c->irq) { ret = wait_event_timeout(i2c->wait, @@ -90,10 +90,13 @@ static int i2c_pca_pf_waitforcompletion(void *pd) } else { /* Do polling */ timeout = jiffies + i2c->adap.timeout; - while (((i2c->algo_data.read_byte(i2c, I2C_PCA_CON) - & I2C_PCA_CON_SI) == 0) - && (ret = time_before(jiffies, timeout))) + do { + ret = time_before(jiffies, timeout); + if (i2c->algo_data.read_byte(i2c, I2C_PCA_CON) + & I2C_PCA_CON_SI) + break; udelay(100); + } while (ret); } return ret > 0; -- cgit v1.2.3 From 64b4782fc9e4bdc59ae90897e2258e4ec938690e Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Thu, 30 Sep 2010 14:14:22 +0200 Subject: i2c: Fix checks which cause legacy suspend to never get called For devices which are not adapted to runtime PM a call to pm_runtime_suspended always returns true. Hence the pm_runtime_suspended checks below prevent legacy suspend from getting called. So do a pm_runtime_suspended check only for devices with a dev_pm_ops populated (which hence do not rely on the legacy suspend.) Signed-off-by: Rajendra Nayak Acked-by: Rafael J. Wysocki Cc: Ben Dooks Cc: Mark Brown Cc: Kevin Hilman Signed-off-by: Jean Delvare --- drivers/i2c/i2c-core.c | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 13927d54cb4e..9b3cac13a4a8 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -197,11 +197,12 @@ static int i2c_device_pm_suspend(struct device *dev) { const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - if (pm_runtime_suspended(dev)) - return 0; - - if (pm) - return pm->suspend ? pm->suspend(dev) : 0; + if (pm) { + if (pm_runtime_suspended(dev)) + return 0; + else + return pm->suspend ? pm->suspend(dev) : 0; + } return i2c_legacy_suspend(dev, PMSG_SUSPEND); } @@ -223,11 +224,12 @@ static int i2c_device_pm_freeze(struct device *dev) { const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - if (pm_runtime_suspended(dev)) - return 0; - - if (pm) - return pm->freeze ? pm->freeze(dev) : 0; + if (pm) { + if (pm_runtime_suspended(dev)) + return 0; + else + return pm->freeze ? pm->freeze(dev) : 0; + } return i2c_legacy_suspend(dev, PMSG_FREEZE); } @@ -236,11 +238,12 @@ static int i2c_device_pm_thaw(struct device *dev) { const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - if (pm_runtime_suspended(dev)) - return 0; - - if (pm) - return pm->thaw ? pm->thaw(dev) : 0; + if (pm) { + if (pm_runtime_suspended(dev)) + return 0; + else + return pm->thaw ? pm->thaw(dev) : 0; + } return i2c_legacy_resume(dev); } @@ -249,11 +252,12 @@ static int i2c_device_pm_poweroff(struct device *dev) { const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - if (pm_runtime_suspended(dev)) - return 0; - - if (pm) - return pm->poweroff ? pm->poweroff(dev) : 0; + if (pm) { + if (pm_runtime_suspended(dev)) + return 0; + else + return pm->poweroff ? pm->poweroff(dev) : 0; + } return i2c_legacy_suspend(dev, PMSG_HIBERNATE); } -- cgit v1.2.3 From 925bb9c649cf8d7200549b395f2ae291833dd494 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 30 Sep 2010 14:14:23 +0200 Subject: of/i2c: Fix module load order issue caused by of_i2c.c Commit 959e85f7, "i2c: add OF-style registration and binding" caused a module dependency loop where of_i2c.c calls functions in i2c-core, and i2c-core calls of_i2c_register_devices() in of_i2c. This means that when i2c support is built as a module when CONFIG_OF is set, then neither i2c_core nor of_i2c are able to be loaded. This patch fixes the problem by moving the of_i2c_register_devices() calls back into the device drivers. Device drivers already specifically request the core code to parse the device tree for devices anyway by setting the of_node pointer, so it isn't a big deal to also call the registration function. The drivers just become slightly more verbose. Signed-off-by: Grant Likely Signed-off-by: Jean Delvare --- drivers/i2c/busses/i2c-cpm.c | 5 +++++ drivers/i2c/busses/i2c-ibm_iic.c | 3 +++ drivers/i2c/busses/i2c-mpc.c | 1 + drivers/i2c/i2c-core.c | 4 ---- 4 files changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index f7bd2613cecc..f2de3be35df3 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c @@ -677,6 +677,11 @@ static int __devinit cpm_i2c_probe(struct platform_device *ofdev, dev_dbg(&ofdev->dev, "hw routines for %s registered.\n", cpm->adap.name); + /* + * register OF I2C devices + */ + of_i2c_register_devices(&cpm->adap); + return 0; out_shut: cpm_i2c_shutdown(cpm); diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index 43ca32fddde2..89eedf45d30e 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -761,6 +761,9 @@ static int __devinit iic_probe(struct platform_device *ofdev, dev_info(&ofdev->dev, "using %s mode\n", dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)"); + /* Now register all the child nodes */ + of_i2c_register_devices(adap); + return 0; error_cleanup: diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index a1c419a716af..b74e6dc6886c 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -632,6 +632,7 @@ static int __devinit fsl_i2c_probe(struct platform_device *op, dev_err(i2c->dev, "failed to add adapter\n"); goto fail_add; } + of_i2c_register_devices(&i2c->adap); return result; diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 9b3cac13a4a8..bea4c5021d26 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -874,9 +873,6 @@ static int i2c_register_adapter(struct i2c_adapter *adap) if (adap->nr < __i2c_first_dynamic_bus_num) i2c_scan_static_board_info(adap); - /* Register devices from the device tree */ - of_i2c_register_devices(adap); - /* Notify drivers */ mutex_lock(&core_lock); bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter); -- cgit v1.2.3 From 7031307aefb6048377385dbb0af2dd43bb0190bb Mon Sep 17 00:00:00 2001 From: MyungJoo Ham Date: Thu, 30 Sep 2010 15:54:46 +0200 Subject: i2c-s3c2410: fix calculation of SDA line delay S3C2440 style I2C controller uses PCLK to calculate the SDA line delay. The driver wrongly assumed that this delay is calculated from the frequency that the controller is operating on. This patch fixes this issue. Signed-off-by: MyungJoo Ham Signed-off-by: Kyungmin Park Signed-off-by: Marek Szyprowski Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-s3c2410.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 72902e0bbfa7..bf831bf81587 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -662,8 +662,8 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got) unsigned long sda_delay; if (pdata->sda_delay) { - sda_delay = (freq / 1000) * pdata->sda_delay; - sda_delay /= 1000000; + sda_delay = clkin * pdata->sda_delay; + sda_delay = DIV_ROUND_UP(sda_delay, 1000000); sda_delay = DIV_ROUND_UP(sda_delay, 5); if (sda_delay > 3) sda_delay = 3; -- cgit v1.2.3 From 8032214346c0c892e859cf6eee6c8ba305cbfe78 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 5 Sep 2010 09:00:22 +0000 Subject: i2c/i2c-pasemi.c: Fix unsigned return type The function has an unsigned return type, but returns a negative constant to indicate an error condition. The result of calling the function is always stored in a variable of type (signed) int, and thus unsigned can be dropped from the return type. A sematic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @exists@ identifier f; constant C; @@ unsigned f(...) { <+... * return -C; ...+> } // Signed-off-by: Julia Lawall Acked-by: Olof Johansson Signed-off-by: Benjamin Herrenschmidt --- drivers/i2c/busses/i2c-pasemi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/i2c') 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; -- cgit v1.2.3 From c5b4afec8e669bbe265daea24037fccfc42c4fe3 Mon Sep 17 00:00:00 2001 From: Jon Povey Date: Tue, 12 Oct 2010 13:47:05 +0900 Subject: i2c-davinci: Fix TX setup for more SoCs This patch is an improvement to 4bba0fd8d1c6d405df666e2573e1a1f917098be0 which got to mainline a little early. Sudhakar Rajashekhara explains that at least OMAP-L138 requires MDR mode settings before DXR for correct behaviour, so load MDR first with STT cleared and later load again with STT set. Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985 Signed-off-by: Jon Povey Acked-by: Troy Kisky Tested-by: Sudhakar Rajashekhara Acked-by: Kevin Hilman Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-davinci.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index b8feac5f2ef4..5795c8398c7c 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -331,21 +331,16 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) INIT_COMPLETION(dev->cmd_complete); dev->cmd_err = 0; - /* Take I2C out of reset, configure it as master and set the - * start bit */ - flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST | DAVINCI_I2C_MDR_STT; + /* Take I2C out of reset and configure it as master */ + flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST; /* if the slave address is ten bit address, enable XA bit */ if (msg->flags & I2C_M_TEN) flag |= DAVINCI_I2C_MDR_XA; if (!(msg->flags & I2C_M_RD)) flag |= DAVINCI_I2C_MDR_TRX; - if (stop) - flag |= DAVINCI_I2C_MDR_STP; - if (msg->len == 0) { + if (msg->len == 0) flag |= DAVINCI_I2C_MDR_RM; - flag &= ~DAVINCI_I2C_MDR_STP; - } /* Enable receive or transmit interrupts */ w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG); @@ -357,18 +352,29 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) dev->terminate = 0; + /* + * Write mode register first as needed for correct behaviour + * on OMAP-L138, but don't set STT yet to avoid a race with XRDY + * occuring before we have loaded DXR + */ + davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); + /* * First byte should be set here, not after interrupt, * because transmit-data-ready interrupt can come before * NACK-interrupt during sending of previous message and * ICDXR may have wrong data + * It also saves us one interrupt, slightly faster */ if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) { davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++); dev->buf_len--; } - /* write the data into mode register; start transmitting */ + /* Set STT to begin transmit now DXR is loaded */ + flag |= DAVINCI_I2C_MDR_STT; + if (stop && msg->len != 0) + flag |= DAVINCI_I2C_MDR_STP; davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); r = wait_for_completion_interruptible_timeout(&dev->cmd_complete, -- cgit v1.2.3 From e39428d53d080ad2615b772d7f99d2a70c2aaab2 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 21 Jun 2010 09:27:05 +0200 Subject: i2c-imx: do not allow interruptions when waiting for I2C to complete The i2c_imx_trx_complete() function is using wait_event_interruptible_timeout() to wait for the I2C controller to signal that it has completed an I2C bus operation. If the process that causes the I2C operation receives a signal, the wait will be interrupted, returning an error. It is better to let the I2C operation finished before handling the signal (i.e. returning into userspace). It is safe to use wait_event_timeout() instead, because the timeout will allow the process to exit if the I2C bus hangs. It's also better to allow the I2C operation to finish, because unacknowledged I2C operations can cause the I2C bus to hang. Signed-off-by: Marc Kleine-Budde Reviewed-by: Wolfram Sang Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-imx.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index d1ff9408dc1f..4c2a62b75b5c 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -159,15 +159,9 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy) static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx) { - int result; - - result = wait_event_interruptible_timeout(i2c_imx->queue, - i2c_imx->i2csr & I2SR_IIF, HZ / 10); + wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10); - if (unlikely(result < 0)) { - dev_dbg(&i2c_imx->adapter.dev, "<%s> result < 0\n", __func__); - return result; - } else if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) { + if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) { dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__); return -ETIMEDOUT; } @@ -295,7 +289,7 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id) i2c_imx->i2csr = temp; temp &= ~I2SR_IIF; writeb(temp, i2c_imx->base + IMX_I2C_I2SR); - wake_up_interruptible(&i2c_imx->queue); + wake_up(&i2c_imx->queue); return IRQ_HANDLED; } -- cgit v1.2.3 From 0a57274ea026c2b7670683947b6cc08b195148cf Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 24 Oct 2010 18:16:57 +0200 Subject: i2c: Fix Kconfig dependencies drivers/i2c/algos/Kconfig makes all the algorithms dependent on !I2C_HELPER_AUTO, which triggers a Kconfig warning about broken dependencies when some driver selects one of the algorithms. Ideally we would make only the prompts dependent on !I2C_HELPER_AUTO, however Kconfig doesn't currently support that. So we have to redefine the symbols separately for the I2C_HELPER_AUTO=y case. Signed-off-by: Jean Delvare Acked-by: Michal Marek --- drivers/i2c/Kconfig | 3 ++- drivers/i2c/algos/Kconfig | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers/i2c') 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/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 -- cgit v1.2.3 From 323584436db0cb05286425d4dfd9516fce88487f Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Sun, 24 Oct 2010 18:16:57 +0200 Subject: i2c-pca-platform: Change device name of request_irq i2c->adap.name shouldn't be used in request_irq. Instead the driver name "i2c-pca-platform" should be used. Signed-off-by: Nobuhiro Iwamatsu Acked-by: Wolfram Sang Cc: stable@kernel.org Signed-off-by: Jean Delvare --- drivers/i2c/busses/i2c-pca-platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/i2c') 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; } -- cgit v1.2.3 From 97cc4d49cfcda1c2dad89c00b62a25b628ce2115 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 24 Oct 2010 18:16:57 +0200 Subject: i2c: Let i2c_parent_is_i2c_adapter return the parent adapter This makes the calling site's code clearer IMHO. Signed-off-by: Jean Delvare Acked-by: Michael Lawnick --- drivers/i2c/i2c-core.c | 30 ++++++++++++++++++------------ drivers/i2c/i2c-dev.c | 13 ++++++------- 2 files changed, 24 insertions(+), 19 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index bea4c5021d26..40e563de0508 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); } 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, -- cgit v1.2.3 From a8d7be818fbe0f8a4e7dc251712958ca369f9d45 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 24 Oct 2010 18:16:58 +0200 Subject: i2c: Remove unneeded inclusions of These drivers don't use anything which is defined in . This header file was never meant to be included directly anyway, and will be deleted soon. Signed-off-by: Jean Delvare Acked-by: Ben Dooks Acked-by: Dave Airlie Cc: Hans Verkuil --- drivers/i2c/busses/i2c-ibm_iic.c | 1 - drivers/i2c/busses/i2c-nuc900.c | 1 - drivers/i2c/busses/i2c-pxa.c | 1 - drivers/i2c/busses/i2c-s3c2410.c | 1 - 4 files changed, 4 deletions(-) (limited to 'drivers/i2c') 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 #include #include -#include #include #include 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 #include -#include #include #include #include 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 #include #include -#include #include #include #include diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index bf831bf81587..6a292ea5e35c 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -24,7 +24,6 @@ #include #include -#include #include #include #include -- cgit v1.2.3 From ef9d9b8fb696850a95cd59ba2cd67991b6f722b3 Mon Sep 17 00:00:00 2001 From: matt mooney Date: Sun, 24 Oct 2010 18:16:58 +0200 Subject: i2c: Change to new flag variable Replace EXTRA_CFLAGS with ccflags-y. Signed-off-by: matt mooney Signed-off-by: Jean Delvare --- drivers/i2c/Makefile | 4 +--- drivers/i2c/algos/Makefile | 4 +--- drivers/i2c/busses/Makefile | 4 +--- drivers/i2c/muxes/Makefile | 4 +--- 4 files changed, 4 insertions(+), 12 deletions(-) (limited to 'drivers/i2c') 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/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/Makefile b/drivers/i2c/busses/Makefile index c3ef49230cba..033ad413f328 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -76,6 +76,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/muxes/Makefile b/drivers/i2c/muxes/Makefile index bd83b5274815..6f497862bdc5 100644 --- a/drivers/i2c/muxes/Makefile +++ b/drivers/i2c/muxes/Makefile @@ -3,6 +3,4 @@ obj-$(CONFIG_I2C_MUX_PCA954x) += pca954x.o -ifeq ($(CONFIG_I2C_DEBUG_BUS),y) -EXTRA_CFLAGS += -DDEBUG -endif +ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG -- cgit v1.2.3 From 9cb2c2726e9ae212ccaeecd3eaadcd8d49ac7400 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 24 Oct 2010 18:16:58 +0200 Subject: i2c-amd8111: Add proper error handling The functions the functions amd_ec_wait_write and amd_ec_wait_read have an unsigned return type, but return a negative constant to indicate an error condition. A sematic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @exists@ identifier f; constant C; @@ unsigned f(...) { <+... * return -C; ...+> } // Fixing amd_ec_wait_write and amd_ec_wait_read leads to the need to adjust the return type of the functions amd_ec_write and amd_ec_read, which are the only functions that call amd_ec_wait_write and amd_ec_wait_read. amd_ec_write and amd_ec_read, in turn, are only called from within the function amd8111_access, which already returns a signed typed value. Each of the calls to amd_ec_write and amd_ec_read are updated using the following semantic patch: // @@ @@ + status = amd_ec_write - amd_ec_write (...); + if (status) return status; @@ @@ + status = amd_ec_read - amd_ec_read (...); + if (status) return status; // The patch also adds the declaration of the status variable. Signed-off-by: Julia Lawall Signed-off-by: Jean Delvare --- drivers/i2c/busses/i2c-amd8111.c | 163 +++++++++++++++++++++++++++------------ 1 file changed, 113 insertions(+), 50 deletions(-) (limited to 'drivers/i2c') 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; } -- cgit v1.2.3 From d57558d0f3b41bb260aaa327150d49f1810461f5 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 24 Oct 2010 18:16:58 +0200 Subject: i2c: Discard warning message on device instantiation from user-space The "new_device" sysfs interface has been there for quite some time now, nobody complained about it so it must be good enough. Time to remove the warning and call it stable. Signed-off-by: Jean Delvare Acked-by: Michael Lawnick --- drivers/i2c/i2c-core.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 40e563de0508..bdadfaf3fe10 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -683,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, ' '); -- cgit v1.2.3 From 51b54ba9bb16b9fc28ec88006778d330af00bf8b Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 24 Oct 2010 18:16:58 +0200 Subject: i2c: Optimize function i2c_detect() Check the class flags before allocating the temporary i2c_client structure, to avoid allocating it when we don't need it. Also optimize the inner loop a bit. Signed-off-by: Jean Delvare Cc: Jacob Pan --- drivers/i2c/i2c-core.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index bdadfaf3fe10..d231f683f576 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1508,26 +1508,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; } -- cgit v1.2.3 From ae63b13bbeca7f8915c555663f8789a531611e4b Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sun, 24 Oct 2010 18:16:58 +0200 Subject: i2c/mux: Driver for PCA9541 I2C Master Selector This patch adds support for PCA9541, an I2C Bus Master Selector. The driver is modeled as single channel I2C Multiplexer to be able to utilize the I2C multiplexer framework. Signed-off-by: Guenter Roeck Reviewed-by: Tom Grennan Acked-by: Jean Delvare --- drivers/i2c/muxes/Kconfig | 10 ++ drivers/i2c/muxes/Makefile | 1 + drivers/i2c/muxes/pca9541.c | 411 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 422 insertions(+) create mode 100644 drivers/i2c/muxes/pca9541.c (limited to 'drivers/i2c') 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 6f497862bdc5..d743806d9b42 100644 --- a/drivers/i2c/muxes/Makefile +++ b/drivers/i2c/muxes/Makefile @@ -1,6 +1,7 @@ # # Makefile for multiplexer I2C chip drivers. +obj-$(CONFIG_I2C_MUX_PCA9541) += pca9541.o obj-$(CONFIG_I2C_MUX_PCA954x) += pca954x.o 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 + * + * Derived from: + * pca954x.c + * + * Copyright (c) 2008-2009 Rodolfo Giometti + * Copyright (c) 2008-2009 Eurotech S.p.A. + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * 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 "); +MODULE_DESCRIPTION("PCA9541 I2C master selector driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From db79f2a1d259a9026241dd0f192c20d6264d5afa Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sun, 24 Oct 2010 18:16:59 +0200 Subject: i2c/pca954x: Remove __devinit and __devexit from probe and remove functions The underlying I2C adapter may or may not be present when this driver gets initialized, and may disappear later, so there is no safe time at which the probe and remove functions can be discarded. Signed-off-by: Guenter Roeck Signed-off-by: Jean Delvare --- drivers/i2c/muxes/pca954x.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/i2c') 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, }; -- cgit v1.2.3 From bf5d95c82692ead9ba7876af73dac2edcc8a6191 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 24 Oct 2010 18:16:59 +0200 Subject: i2c-viapro: Don't log nacks Transactions not acked can happen every now and then, in particular during device detection, and various transaction types can be used for this purpose. So stop logging this event, except when debugging is enabled. This is what other similar drivers (e.g. i2c-i801 or i2c-piix4) do. Signed-off-by: Jean Delvare --- drivers/i2c/busses/i2c-viapro.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers/i2c') 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 */ -- cgit v1.2.3 From 8df399018df120d28f89fda6f2515cc6e096e43d Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Sat, 23 Oct 2010 07:07:00 +0900 Subject: sh: i2c-sh7760: Replase from ctrl_* to __raw_* ctrl_* is deprecated. We should to use __raw_*. Signed-off-by: Nobuhiro Iwamatsu Signed-off-by: Paul Mundt --- drivers/i2c/busses/i2c-sh7760.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/i2c') 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) -- cgit v1.2.3