Commit e748a385 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:
 "These should have been in rc2 but I missed it due to working on devm
  longer than expected.

  There is one ID addition, since we are touching the driver anyhow.
  And the feature bit documentation is one outcome of a debug session
  and will make it easier for users to work around problems.  The rest
  is typical driver bugfixes."

* 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
  i2c: suppress lockdep warning on delete_device
  i2c: mv64xxx: work around signals causing I2C transactions to be aborted
  i2c: i801: Document feature bits in modinfo
  i2c: designware: add Intel BayTrail ACPI ID
  i2c: designware: always clear interrupts before enabling them
  i2c: designware: fix RX FIFO overrun
parents c4ad180f e9b526fe
...@@ -383,7 +383,8 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) ...@@ -383,7 +383,8 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
/* Enable the adapter */ /* Enable the adapter */
__i2c_dw_enable(dev, true); __i2c_dw_enable(dev, true);
/* Enable interrupts */ /* Clear and enable interrupts */
i2c_dw_clear_int(dev);
dw_writel(dev, DW_IC_INTR_DEFAULT_MASK, DW_IC_INTR_MASK); dw_writel(dev, DW_IC_INTR_DEFAULT_MASK, DW_IC_INTR_MASK);
} }
...@@ -448,8 +449,14 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev) ...@@ -448,8 +449,14 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
cmd |= BIT(9); cmd |= BIT(9);
if (msgs[dev->msg_write_idx].flags & I2C_M_RD) { if (msgs[dev->msg_write_idx].flags & I2C_M_RD) {
/* avoid rx buffer overrun */
if (rx_limit - dev->rx_outstanding <= 0)
break;
dw_writel(dev, cmd | 0x100, DW_IC_DATA_CMD); dw_writel(dev, cmd | 0x100, DW_IC_DATA_CMD);
rx_limit--; rx_limit--;
dev->rx_outstanding++;
} else } else
dw_writel(dev, cmd | *buf++, DW_IC_DATA_CMD); dw_writel(dev, cmd | *buf++, DW_IC_DATA_CMD);
tx_limit--; buf_len--; tx_limit--; buf_len--;
...@@ -502,8 +509,10 @@ i2c_dw_read(struct dw_i2c_dev *dev) ...@@ -502,8 +509,10 @@ i2c_dw_read(struct dw_i2c_dev *dev)
rx_valid = dw_readl(dev, DW_IC_RXFLR); rx_valid = dw_readl(dev, DW_IC_RXFLR);
for (; len > 0 && rx_valid > 0; len--, rx_valid--) for (; len > 0 && rx_valid > 0; len--, rx_valid--) {
*buf++ = dw_readl(dev, DW_IC_DATA_CMD); *buf++ = dw_readl(dev, DW_IC_DATA_CMD);
dev->rx_outstanding--;
}
if (len > 0) { if (len > 0) {
dev->status |= STATUS_READ_IN_PROGRESS; dev->status |= STATUS_READ_IN_PROGRESS;
...@@ -561,6 +570,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) ...@@ -561,6 +570,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
dev->msg_err = 0; dev->msg_err = 0;
dev->status = STATUS_IDLE; dev->status = STATUS_IDLE;
dev->abort_source = 0; dev->abort_source = 0;
dev->rx_outstanding = 0;
ret = i2c_dw_wait_bus_not_busy(dev); ret = i2c_dw_wait_bus_not_busy(dev);
if (ret < 0) if (ret < 0)
......
...@@ -60,6 +60,7 @@ ...@@ -60,6 +60,7 @@
* @adapter: i2c subsystem adapter node * @adapter: i2c subsystem adapter node
* @tx_fifo_depth: depth of the hardware tx fifo * @tx_fifo_depth: depth of the hardware tx fifo
* @rx_fifo_depth: depth of the hardware rx fifo * @rx_fifo_depth: depth of the hardware rx fifo
* @rx_outstanding: current master-rx elements in tx fifo
*/ */
struct dw_i2c_dev { struct dw_i2c_dev {
struct device *dev; struct device *dev;
...@@ -88,6 +89,7 @@ struct dw_i2c_dev { ...@@ -88,6 +89,7 @@ struct dw_i2c_dev {
u32 master_cfg; u32 master_cfg;
unsigned int tx_fifo_depth; unsigned int tx_fifo_depth;
unsigned int rx_fifo_depth; unsigned int rx_fifo_depth;
int rx_outstanding;
}; };
#define ACCESS_SWAP 0x00000001 #define ACCESS_SWAP 0x00000001
......
...@@ -69,6 +69,7 @@ static int dw_i2c_acpi_configure(struct platform_device *pdev) ...@@ -69,6 +69,7 @@ static int dw_i2c_acpi_configure(struct platform_device *pdev)
static const struct acpi_device_id dw_i2c_acpi_match[] = { static const struct acpi_device_id dw_i2c_acpi_match[] = {
{ "INT33C2", 0 }, { "INT33C2", 0 },
{ "INT33C3", 0 }, { "INT33C3", 0 },
{ "80860F41", 0 },
{ } { }
}; };
MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match); MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match);
......
...@@ -231,7 +231,11 @@ static const char *i801_feature_names[] = { ...@@ -231,7 +231,11 @@ static const char *i801_feature_names[] = {
static unsigned int disable_features; static unsigned int disable_features;
module_param(disable_features, uint, S_IRUGO | S_IWUSR); module_param(disable_features, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(disable_features, "Disable selected driver features"); MODULE_PARM_DESC(disable_features, "Disable selected driver features:\n"
"\t\t 0x01 disable SMBus PEC\n"
"\t\t 0x02 disable the block buffer\n"
"\t\t 0x08 disable the I2C block read functionality\n"
"\t\t 0x10 don't use interrupts ");
/* Make sure the SMBus host is ready to start transmitting. /* Make sure the SMBus host is ready to start transmitting.
Return 0 if it is, -EBUSY if it is not. */ Return 0 if it is, -EBUSY if it is not. */
......
...@@ -252,7 +252,7 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) ...@@ -252,7 +252,7 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
writel(drv_data->cntl_bits, writel(drv_data->cntl_bits,
drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
drv_data->block = 0; drv_data->block = 0;
wake_up_interruptible(&drv_data->waitq); wake_up(&drv_data->waitq);
break; break;
case MV64XXX_I2C_ACTION_CONTINUE: case MV64XXX_I2C_ACTION_CONTINUE:
...@@ -300,7 +300,7 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) ...@@ -300,7 +300,7 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP, writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP,
drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
drv_data->block = 0; drv_data->block = 0;
wake_up_interruptible(&drv_data->waitq); wake_up(&drv_data->waitq);
break; break;
case MV64XXX_I2C_ACTION_INVALID: case MV64XXX_I2C_ACTION_INVALID:
...@@ -315,7 +315,7 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) ...@@ -315,7 +315,7 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP, writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP,
drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
drv_data->block = 0; drv_data->block = 0;
wake_up_interruptible(&drv_data->waitq); wake_up(&drv_data->waitq);
break; break;
} }
} }
...@@ -381,7 +381,7 @@ mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data) ...@@ -381,7 +381,7 @@ mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data)
unsigned long flags; unsigned long flags;
char abort = 0; char abort = 0;
time_left = wait_event_interruptible_timeout(drv_data->waitq, time_left = wait_event_timeout(drv_data->waitq,
!drv_data->block, drv_data->adapter.timeout); !drv_data->block, drv_data->adapter.timeout);
spin_lock_irqsave(&drv_data->lock, flags); spin_lock_irqsave(&drv_data->lock, flags);
......
...@@ -892,7 +892,8 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr, ...@@ -892,7 +892,8 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr,
} }
static DEVICE_ATTR(new_device, S_IWUSR, NULL, i2c_sysfs_new_device); static DEVICE_ATTR(new_device, S_IWUSR, NULL, i2c_sysfs_new_device);
static DEVICE_ATTR(delete_device, S_IWUSR, NULL, i2c_sysfs_delete_device); static DEVICE_ATTR_IGNORE_LOCKDEP(delete_device, S_IWUSR, NULL,
i2c_sysfs_delete_device);
static struct attribute *i2c_adapter_attrs[] = { static struct attribute *i2c_adapter_attrs[] = {
&dev_attr_name.attr, &dev_attr_name.attr,
......
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