提交 33f14593 编写于 作者: L Linus Torvalds

Merge branch 'i2c-embedded/for-current' of git://git.pengutronix.de/git/wsa/linux

Pull i2c fixes from Wolfram Sang:
 "Bugfixes for the i2c subsystem.

  Except for a few one-liners, there is mainly one revert because of an
  overlooked dependency.  Since there is no linux-next at the moment, I
  did some extra testing, and all was fine for me."

* 'i2c-embedded/for-current' of git://git.pengutronix.de/git/wsa/linux:
  i2c: mxs: Handle i2c DMA failure properly
  i2c: s3c2410: Fix code to free gpios
  i2c: omap: ensure writes to dev->buf_len are ordered
  Revert "ARM: OMAP: convert I2C driver to PM QoS for MPU latency constraints"
  i2c: at91: fix SMBus quick command
...@@ -26,12 +26,14 @@ ...@@ -26,12 +26,14 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-omap.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <mach/irqs.h> #include <mach/irqs.h>
#include <plat/i2c.h> #include <plat/i2c.h>
#include <plat/omap-pm.h>
#include <plat/omap_device.h> #include <plat/omap_device.h>
#define OMAP_I2C_SIZE 0x3f #define OMAP_I2C_SIZE 0x3f
...@@ -127,6 +129,16 @@ static inline int omap1_i2c_add_bus(int bus_id) ...@@ -127,6 +129,16 @@ static inline int omap1_i2c_add_bus(int bus_id)
#ifdef CONFIG_ARCH_OMAP2PLUS #ifdef CONFIG_ARCH_OMAP2PLUS
/*
* XXX This function is a temporary compatibility wrapper - only
* needed until the I2C driver can be converted to call
* omap_pm_set_max_dev_wakeup_lat() and handle a return code.
*/
static void omap_pm_set_max_mpu_wakeup_lat_compat(struct device *dev, long t)
{
omap_pm_set_max_mpu_wakeup_lat(dev, t);
}
static inline int omap2_i2c_add_bus(int bus_id) static inline int omap2_i2c_add_bus(int bus_id)
{ {
int l; int l;
...@@ -158,6 +170,15 @@ static inline int omap2_i2c_add_bus(int bus_id) ...@@ -158,6 +170,15 @@ static inline int omap2_i2c_add_bus(int bus_id)
dev_attr = (struct omap_i2c_dev_attr *)oh->dev_attr; dev_attr = (struct omap_i2c_dev_attr *)oh->dev_attr;
pdata->flags = dev_attr->flags; pdata->flags = dev_attr->flags;
/*
* When waiting for completion of a i2c transfer, we need to
* set a wake up latency constraint for the MPU. This is to
* ensure quick enough wakeup from idle, when transfer
* completes.
* Only omap3 has support for constraints
*/
if (cpu_is_omap34xx())
pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat;
pdev = omap_device_build(name, bus_id, oh, pdata, pdev = omap_device_build(name, bus_id, oh, pdata,
sizeof(struct omap_i2c_bus_platform_data), sizeof(struct omap_i2c_bus_platform_data),
NULL, 0, 0); NULL, 0, 0);
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#define AT91_TWI_STOP 0x0002 /* Send a Stop Condition */ #define AT91_TWI_STOP 0x0002 /* Send a Stop Condition */
#define AT91_TWI_MSEN 0x0004 /* Master Transfer Enable */ #define AT91_TWI_MSEN 0x0004 /* Master Transfer Enable */
#define AT91_TWI_SVDIS 0x0020 /* Slave Transfer Disable */ #define AT91_TWI_SVDIS 0x0020 /* Slave Transfer Disable */
#define AT91_TWI_QUICK 0x0040 /* SMBus quick command */
#define AT91_TWI_SWRST 0x0080 /* Software Reset */ #define AT91_TWI_SWRST 0x0080 /* Software Reset */
#define AT91_TWI_MMR 0x0004 /* Master Mode Register */ #define AT91_TWI_MMR 0x0004 /* Master Mode Register */
...@@ -212,7 +213,11 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev) ...@@ -212,7 +213,11 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
INIT_COMPLETION(dev->cmd_complete); INIT_COMPLETION(dev->cmd_complete);
dev->transfer_status = 0; dev->transfer_status = 0;
if (dev->msg->flags & I2C_M_RD) {
if (!dev->buf_len) {
at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_QUICK);
at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_TXCOMP);
} else if (dev->msg->flags & I2C_M_RD) {
unsigned start_flags = AT91_TWI_START; unsigned start_flags = AT91_TWI_START;
if (at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_RXRDY) { if (at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_RXRDY) {
......
...@@ -287,12 +287,14 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap, ...@@ -287,12 +287,14 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
select_init_dma_fail: select_init_dma_fail:
dma_unmap_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE); dma_unmap_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE);
select_init_pio_fail: select_init_pio_fail:
dmaengine_terminate_all(i2c->dmach);
return -EINVAL; return -EINVAL;
/* Write failpath. */ /* Write failpath. */
write_init_dma_fail: write_init_dma_fail:
dma_unmap_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE); dma_unmap_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);
write_init_pio_fail: write_init_pio_fail:
dmaengine_terminate_all(i2c->dmach);
return -EINVAL; return -EINVAL;
} }
......
...@@ -43,7 +43,6 @@ ...@@ -43,7 +43,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/i2c-omap.h> #include <linux/i2c-omap.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/pm_qos.h>
/* I2C controller revisions */ /* I2C controller revisions */
#define OMAP_I2C_OMAP1_REV_2 0x20 #define OMAP_I2C_OMAP1_REV_2 0x20
...@@ -187,8 +186,9 @@ struct omap_i2c_dev { ...@@ -187,8 +186,9 @@ struct omap_i2c_dev {
int reg_shift; /* bit shift for I2C register addresses */ int reg_shift; /* bit shift for I2C register addresses */
struct completion cmd_complete; struct completion cmd_complete;
struct resource *ioarea; struct resource *ioarea;
u32 latency; /* maximum MPU wkup latency */ u32 latency; /* maximum mpu wkup latency */
struct pm_qos_request pm_qos_request; void (*set_mpu_wkup_lat)(struct device *dev,
long latency);
u32 speed; /* Speed of bus in kHz */ u32 speed; /* Speed of bus in kHz */
u32 dtrev; /* extra revision from DT */ u32 dtrev; /* extra revision from DT */
u32 flags; u32 flags;
...@@ -494,7 +494,9 @@ static void omap_i2c_resize_fifo(struct omap_i2c_dev *dev, u8 size, bool is_rx) ...@@ -494,7 +494,9 @@ static void omap_i2c_resize_fifo(struct omap_i2c_dev *dev, u8 size, bool is_rx)
dev->b_hw = 1; /* Enable hardware fixes */ dev->b_hw = 1; /* Enable hardware fixes */
/* calculate wakeup latency constraint for MPU */ /* calculate wakeup latency constraint for MPU */
dev->latency = (1000000 * dev->threshold) / (1000 * dev->speed / 8); if (dev->set_mpu_wkup_lat != NULL)
dev->latency = (1000000 * dev->threshold) /
(1000 * dev->speed / 8);
} }
/* /*
...@@ -522,6 +524,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, ...@@ -522,6 +524,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
dev->buf = msg->buf; dev->buf = msg->buf;
dev->buf_len = msg->len; dev->buf_len = msg->len;
/* make sure writes to dev->buf_len are ordered */
barrier();
omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len); omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len);
/* Clear the FIFO Buffers */ /* Clear the FIFO Buffers */
...@@ -579,7 +584,6 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, ...@@ -579,7 +584,6 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
*/ */
timeout = wait_for_completion_timeout(&dev->cmd_complete, timeout = wait_for_completion_timeout(&dev->cmd_complete,
OMAP_I2C_TIMEOUT); OMAP_I2C_TIMEOUT);
dev->buf_len = 0;
if (timeout == 0) { if (timeout == 0) {
dev_err(dev->dev, "controller timed out\n"); dev_err(dev->dev, "controller timed out\n");
omap_i2c_init(dev); omap_i2c_init(dev);
...@@ -629,16 +633,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) ...@@ -629,16 +633,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
if (r < 0) if (r < 0)
goto out; goto out;
/* if (dev->set_mpu_wkup_lat != NULL)
* When waiting for completion of a i2c transfer, we need to dev->set_mpu_wkup_lat(dev->dev, dev->latency);
* set a wake up latency constraint for the MPU. This is to
* ensure quick enough wakeup from idle, when transfer
* completes.
*/
if (dev->latency)
pm_qos_add_request(&dev->pm_qos_request,
PM_QOS_CPU_DMA_LATENCY,
dev->latency);
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1))); r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1)));
...@@ -646,8 +642,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) ...@@ -646,8 +642,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
break; break;
} }
if (dev->latency) if (dev->set_mpu_wkup_lat != NULL)
pm_qos_remove_request(&dev->pm_qos_request); dev->set_mpu_wkup_lat(dev->dev, -1);
if (r == 0) if (r == 0)
r = num; r = num;
...@@ -1104,6 +1100,7 @@ omap_i2c_probe(struct platform_device *pdev) ...@@ -1104,6 +1100,7 @@ omap_i2c_probe(struct platform_device *pdev)
} else if (pdata != NULL) { } else if (pdata != NULL) {
dev->speed = pdata->clkrate; dev->speed = pdata->clkrate;
dev->flags = pdata->flags; dev->flags = pdata->flags;
dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat;
dev->dtrev = pdata->rev; dev->dtrev = pdata->rev;
} }
...@@ -1159,8 +1156,9 @@ omap_i2c_probe(struct platform_device *pdev) ...@@ -1159,8 +1156,9 @@ omap_i2c_probe(struct platform_device *pdev)
dev->b_hw = 1; /* Enable hardware fixes */ dev->b_hw = 1; /* Enable hardware fixes */
/* calculate wakeup latency constraint for MPU */ /* calculate wakeup latency constraint for MPU */
dev->latency = (1000000 * dev->fifo_size) / if (dev->set_mpu_wkup_lat != NULL)
(1000 * dev->speed / 8); dev->latency = (1000000 * dev->fifo_size) /
(1000 * dev->speed / 8);
} }
/* reset ASAP, clearing any IRQs */ /* reset ASAP, clearing any IRQs */
......
...@@ -806,6 +806,7 @@ static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c) ...@@ -806,6 +806,7 @@ static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c)
dev_err(i2c->dev, "invalid gpio[%d]: %d\n", idx, gpio); dev_err(i2c->dev, "invalid gpio[%d]: %d\n", idx, gpio);
goto free_gpio; goto free_gpio;
} }
i2c->gpios[idx] = gpio;
ret = gpio_request(gpio, "i2c-bus"); ret = gpio_request(gpio, "i2c-bus");
if (ret) { if (ret) {
......
...@@ -34,6 +34,7 @@ struct omap_i2c_bus_platform_data { ...@@ -34,6 +34,7 @@ struct omap_i2c_bus_platform_data {
u32 clkrate; u32 clkrate;
u32 rev; u32 rev;
u32 flags; u32 flags;
void (*set_mpu_wkup_lat)(struct device *dev, long set);
}; };
#endif #endif
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册