Commit 658874f0 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'i2c-fixes-rc4' of git://aeryn.fluff.org.uk/bjdooks/linux

* 'i2c-fixes-rc4' of git://aeryn.fluff.org.uk/bjdooks/linux:
  i2c-omap: OMAP3430 Silicon Errata 1.153
  i2c-omap: In case of a NACK|ARDY|AL return from the ISR
  i2c-omap: Bug in reading the RXSTAT/TXSTAT values from the I2C_BUFFSTAT register
  i2c-sh_mobile: change module_init() to subsys_initcall()
  i2c: strncpy does not null terminate string
  i2c-s3c2410: s3c24xx_i2c_init: don't clobber IICLC value
parents 91a5698d cd086d3a
...@@ -672,9 +672,10 @@ omap_i2c_isr(int this_irq, void *dev_id) ...@@ -672,9 +672,10 @@ omap_i2c_isr(int this_irq, void *dev_id)
break; break;
} }
err = 0;
complete:
omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat); omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
err = 0;
if (stat & OMAP_I2C_STAT_NACK) { if (stat & OMAP_I2C_STAT_NACK) {
err |= OMAP_I2C_STAT_NACK; err |= OMAP_I2C_STAT_NACK;
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
...@@ -685,16 +686,19 @@ omap_i2c_isr(int this_irq, void *dev_id) ...@@ -685,16 +686,19 @@ omap_i2c_isr(int this_irq, void *dev_id)
err |= OMAP_I2C_STAT_AL; err |= OMAP_I2C_STAT_AL;
} }
if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK | if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK |
OMAP_I2C_STAT_AL)) OMAP_I2C_STAT_AL)) {
omap_i2c_complete_cmd(dev, err); omap_i2c_complete_cmd(dev, err);
return IRQ_HANDLED;
}
if (stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)) { if (stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)) {
u8 num_bytes = 1; u8 num_bytes = 1;
if (dev->fifo_size) { if (dev->fifo_size) {
if (stat & OMAP_I2C_STAT_RRDY) if (stat & OMAP_I2C_STAT_RRDY)
num_bytes = dev->fifo_size; num_bytes = dev->fifo_size;
else else /* read RXSTAT on RDR interrupt */
num_bytes = omap_i2c_read_reg(dev, num_bytes = (omap_i2c_read_reg(dev,
OMAP_I2C_BUFSTAT_REG); OMAP_I2C_BUFSTAT_REG)
>> 8) & 0x3F;
} }
while (num_bytes) { while (num_bytes) {
num_bytes--; num_bytes--;
...@@ -731,9 +735,10 @@ omap_i2c_isr(int this_irq, void *dev_id) ...@@ -731,9 +735,10 @@ omap_i2c_isr(int this_irq, void *dev_id)
if (dev->fifo_size) { if (dev->fifo_size) {
if (stat & OMAP_I2C_STAT_XRDY) if (stat & OMAP_I2C_STAT_XRDY)
num_bytes = dev->fifo_size; num_bytes = dev->fifo_size;
else else /* read TXSTAT on XDR interrupt */
num_bytes = omap_i2c_read_reg(dev, num_bytes = omap_i2c_read_reg(dev,
OMAP_I2C_BUFSTAT_REG); OMAP_I2C_BUFSTAT_REG)
& 0x3F;
} }
while (num_bytes) { while (num_bytes) {
num_bytes--; num_bytes--;
...@@ -760,6 +765,27 @@ omap_i2c_isr(int this_irq, void *dev_id) ...@@ -760,6 +765,27 @@ omap_i2c_isr(int this_irq, void *dev_id)
"data to send\n"); "data to send\n");
break; break;
} }
/*
* OMAP3430 Errata 1.153: When an XRDY/XDR
* is hit, wait for XUDF before writing data
* to DATA_REG. Otherwise some data bytes can
* be lost while transferring them from the
* memory to the I2C interface.
*/
if (cpu_is_omap34xx()) {
while (!(stat & OMAP_I2C_STAT_XUDF)) {
if (stat & (OMAP_I2C_STAT_NACK | OMAP_I2C_STAT_AL)) {
omap_i2c_ack_stat(dev, stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
err |= OMAP_I2C_STAT_XUDF;
goto complete;
}
cpu_relax();
stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
}
}
omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w); omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
} }
omap_i2c_ack_stat(dev, omap_i2c_ack_stat(dev,
...@@ -879,7 +905,7 @@ omap_i2c_probe(struct platform_device *pdev) ...@@ -879,7 +905,7 @@ omap_i2c_probe(struct platform_device *pdev)
i2c_set_adapdata(adap, dev); i2c_set_adapdata(adap, dev);
adap->owner = THIS_MODULE; adap->owner = THIS_MODULE;
adap->class = I2C_CLASS_HWMON; adap->class = I2C_CLASS_HWMON;
strncpy(adap->name, "OMAP I2C adapter", sizeof(adap->name)); strlcpy(adap->name, "OMAP I2C adapter", sizeof(adap->name));
adap->algo = &omap_i2c_algo; adap->algo = &omap_i2c_algo;
adap->dev.parent = &pdev->dev; adap->dev.parent = &pdev->dev;
......
...@@ -763,11 +763,6 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) ...@@ -763,11 +763,6 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
dev_info(i2c->dev, "bus frequency set to %d KHz\n", freq); dev_info(i2c->dev, "bus frequency set to %d KHz\n", freq);
dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02lx\n", iicon); dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02lx\n", iicon);
/* check for s3c2440 i2c controller */
if (s3c24xx_i2c_is2440(i2c))
writel(0x0, i2c->regs + S3C2440_IICLC);
return 0; return 0;
} }
......
...@@ -637,7 +637,7 @@ static void __exit sh_mobile_i2c_adap_exit(void) ...@@ -637,7 +637,7 @@ static void __exit sh_mobile_i2c_adap_exit(void)
platform_driver_unregister(&sh_mobile_i2c_driver); platform_driver_unregister(&sh_mobile_i2c_driver);
} }
module_init(sh_mobile_i2c_adap_init); subsys_initcall(sh_mobile_i2c_adap_init);
module_exit(sh_mobile_i2c_adap_exit); module_exit(sh_mobile_i2c_adap_exit);
MODULE_DESCRIPTION("SuperH Mobile I2C Bus Controller driver"); MODULE_DESCRIPTION("SuperH Mobile I2C Bus Controller driver");
......
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