Commit 86ba8b0a authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux

Pull i2c bugfixes from Wolfram Sang:
 "I2C driver bugfixes for the 3.17 release.  Details can be found in the
  commit messages, yet I think this is typical driver stuff"

* 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
  Revert "i2c: rcar: remove spinlock"
  i2c: at91: add bound checking on SMBus block length bytes
  i2c: rk3x: fix bug that cause transfer fails in master receive mode
  i2c: at91: Fix a race condition during signal handling in at91_do_twi_xfer.
  i2c: mv64xxx: continue probe when clock-frequency is missing
  i2c: rcar: fix MNR interrupt handling
parents fb762340 91bfe298
...@@ -101,6 +101,7 @@ struct at91_twi_dev { ...@@ -101,6 +101,7 @@ struct at91_twi_dev {
unsigned twi_cwgr_reg; unsigned twi_cwgr_reg;
struct at91_twi_pdata *pdata; struct at91_twi_pdata *pdata;
bool use_dma; bool use_dma;
bool recv_len_abort;
struct at91_twi_dma dma; struct at91_twi_dma dma;
}; };
...@@ -267,12 +268,24 @@ static void at91_twi_read_next_byte(struct at91_twi_dev *dev) ...@@ -267,12 +268,24 @@ static void at91_twi_read_next_byte(struct at91_twi_dev *dev)
*dev->buf = at91_twi_read(dev, AT91_TWI_RHR) & 0xff; *dev->buf = at91_twi_read(dev, AT91_TWI_RHR) & 0xff;
--dev->buf_len; --dev->buf_len;
/* return if aborting, we only needed to read RHR to clear RXRDY*/
if (dev->recv_len_abort)
return;
/* handle I2C_SMBUS_BLOCK_DATA */ /* handle I2C_SMBUS_BLOCK_DATA */
if (unlikely(dev->msg->flags & I2C_M_RECV_LEN)) { if (unlikely(dev->msg->flags & I2C_M_RECV_LEN)) {
/* ensure length byte is a valid value */
if (*dev->buf <= I2C_SMBUS_BLOCK_MAX && *dev->buf > 0) {
dev->msg->flags &= ~I2C_M_RECV_LEN; dev->msg->flags &= ~I2C_M_RECV_LEN;
dev->buf_len += *dev->buf; dev->buf_len += *dev->buf;
dev->msg->len = dev->buf_len + 1; dev->msg->len = dev->buf_len + 1;
dev_dbg(dev->dev, "received block length %d\n", dev->buf_len); dev_dbg(dev->dev, "received block length %d\n",
dev->buf_len);
} else {
/* abort and send the stop by reading one more byte */
dev->recv_len_abort = true;
dev->buf_len = 1;
}
} }
/* send stop if second but last byte has been read */ /* send stop if second but last byte has been read */
...@@ -421,7 +434,7 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev) ...@@ -421,7 +434,7 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
} }
} }
ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, ret = wait_for_completion_io_timeout(&dev->cmd_complete,
dev->adapter.timeout); dev->adapter.timeout);
if (ret == 0) { if (ret == 0) {
dev_err(dev->dev, "controller timed out\n"); dev_err(dev->dev, "controller timed out\n");
...@@ -444,6 +457,12 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev) ...@@ -444,6 +457,12 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
ret = -EIO; ret = -EIO;
goto error; goto error;
} }
if (dev->recv_len_abort) {
dev_err(dev->dev, "invalid smbus block length recvd\n");
ret = -EPROTO;
goto error;
}
dev_dbg(dev->dev, "transfer complete\n"); dev_dbg(dev->dev, "transfer complete\n");
return 0; return 0;
...@@ -500,6 +519,7 @@ static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num) ...@@ -500,6 +519,7 @@ static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
dev->buf_len = m_start->len; dev->buf_len = m_start->len;
dev->buf = m_start->buf; dev->buf = m_start->buf;
dev->msg = m_start; dev->msg = m_start;
dev->recv_len_abort = false;
ret = at91_do_twi_transfer(dev); ret = at91_do_twi_transfer(dev);
......
...@@ -746,8 +746,7 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, ...@@ -746,8 +746,7 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
} }
tclk = clk_get_rate(drv_data->clk); tclk = clk_get_rate(drv_data->clk);
rc = of_property_read_u32(np, "clock-frequency", &bus_freq); if (of_property_read_u32(np, "clock-frequency", &bus_freq))
if (rc)
bus_freq = 100000; /* 100kHz by default */ bus_freq = 100000; /* 100kHz by default */
if (!mv64xxx_find_baud_factors(bus_freq, tclk, if (!mv64xxx_find_baud_factors(bus_freq, tclk,
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spinlock.h>
/* register offsets */ /* register offsets */
#define ICSCR 0x00 /* slave ctrl */ #define ICSCR 0x00 /* slave ctrl */
...@@ -95,6 +96,7 @@ struct rcar_i2c_priv { ...@@ -95,6 +96,7 @@ struct rcar_i2c_priv {
struct i2c_msg *msg; struct i2c_msg *msg;
struct clk *clk; struct clk *clk;
spinlock_t lock;
wait_queue_head_t wait; wait_queue_head_t wait;
int pos; int pos;
...@@ -365,20 +367,20 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr) ...@@ -365,20 +367,20 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
struct rcar_i2c_priv *priv = ptr; struct rcar_i2c_priv *priv = ptr;
u32 msr; u32 msr;
/*-------------- spin lock -----------------*/
spin_lock(&priv->lock);
msr = rcar_i2c_read(priv, ICMSR); msr = rcar_i2c_read(priv, ICMSR);
/* Only handle interrupts that are currently enabled */
msr &= rcar_i2c_read(priv, ICMIER);
/* Arbitration lost */ /* Arbitration lost */
if (msr & MAL) { if (msr & MAL) {
rcar_i2c_flags_set(priv, (ID_DONE | ID_ARBLOST)); rcar_i2c_flags_set(priv, (ID_DONE | ID_ARBLOST));
goto out; goto out;
} }
/* Stop */
if (msr & MST) {
rcar_i2c_flags_set(priv, ID_DONE);
goto out;
}
/* Nack */ /* Nack */
if (msr & MNR) { if (msr & MNR) {
/* go to stop phase */ /* go to stop phase */
...@@ -388,6 +390,12 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr) ...@@ -388,6 +390,12 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
goto out; goto out;
} }
/* Stop */
if (msr & MST) {
rcar_i2c_flags_set(priv, ID_DONE);
goto out;
}
if (rcar_i2c_is_recv(priv)) if (rcar_i2c_is_recv(priv))
rcar_i2c_flags_set(priv, rcar_i2c_irq_recv(priv, msr)); rcar_i2c_flags_set(priv, rcar_i2c_irq_recv(priv, msr));
else else
...@@ -400,6 +408,9 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr) ...@@ -400,6 +408,9 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
wake_up(&priv->wait); wake_up(&priv->wait);
} }
spin_unlock(&priv->lock);
/*-------------- spin unlock -----------------*/
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -409,14 +420,21 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap, ...@@ -409,14 +420,21 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
{ {
struct rcar_i2c_priv *priv = i2c_get_adapdata(adap); struct rcar_i2c_priv *priv = i2c_get_adapdata(adap);
struct device *dev = rcar_i2c_priv_to_dev(priv); struct device *dev = rcar_i2c_priv_to_dev(priv);
unsigned long flags;
int i, ret, timeout; int i, ret, timeout;
pm_runtime_get_sync(dev); pm_runtime_get_sync(dev);
/*-------------- spin lock -----------------*/
spin_lock_irqsave(&priv->lock, flags);
rcar_i2c_init(priv); rcar_i2c_init(priv);
/* start clock */ /* start clock */
rcar_i2c_write(priv, ICCCR, priv->icccr); rcar_i2c_write(priv, ICCCR, priv->icccr);
spin_unlock_irqrestore(&priv->lock, flags);
/*-------------- spin unlock -----------------*/
ret = rcar_i2c_bus_barrier(priv); ret = rcar_i2c_bus_barrier(priv);
if (ret < 0) if (ret < 0)
goto out; goto out;
...@@ -428,6 +446,9 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap, ...@@ -428,6 +446,9 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
break; break;
} }
/*-------------- spin lock -----------------*/
spin_lock_irqsave(&priv->lock, flags);
/* init each data */ /* init each data */
priv->msg = &msgs[i]; priv->msg = &msgs[i];
priv->pos = 0; priv->pos = 0;
...@@ -437,6 +458,9 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap, ...@@ -437,6 +458,9 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
ret = rcar_i2c_prepare_msg(priv); ret = rcar_i2c_prepare_msg(priv);
spin_unlock_irqrestore(&priv->lock, flags);
/*-------------- spin unlock -----------------*/
if (ret < 0) if (ret < 0)
break; break;
...@@ -540,6 +564,7 @@ static int rcar_i2c_probe(struct platform_device *pdev) ...@@ -540,6 +564,7 @@ static int rcar_i2c_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
init_waitqueue_head(&priv->wait); init_waitqueue_head(&priv->wait);
spin_lock_init(&priv->lock);
adap = &priv->adap; adap = &priv->adap;
adap->nr = pdev->id; adap->nr = pdev->id;
......
...@@ -323,6 +323,10 @@ static void rk3x_i2c_handle_read(struct rk3x_i2c *i2c, unsigned int ipd) ...@@ -323,6 +323,10 @@ static void rk3x_i2c_handle_read(struct rk3x_i2c *i2c, unsigned int ipd)
/* ack interrupt */ /* ack interrupt */
i2c_writel(i2c, REG_INT_MBRF, REG_IPD); i2c_writel(i2c, REG_INT_MBRF, REG_IPD);
/* Can only handle a maximum of 32 bytes at a time */
if (len > 32)
len = 32;
/* read the data from receive buffer */ /* read the data from receive buffer */
for (i = 0; i < len; ++i) { for (i = 0; i < len; ++i) {
if (i % 4 == 0) if (i % 4 == 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment