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
This commit is contained in:
commit
658874f05d
3 changed files with 35 additions and 14 deletions
|
@ -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)
|
||||||
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)
|
||||||
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)
|
||||||
"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)
|
||||||
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)
|
||||||
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)
|
||||||
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");
|
||||||
|
|
Loading…
Reference in a new issue