diff options
| -rw-r--r-- | drivers/i2c/busses/i2c-omap.c | 40 | 
1 files changed, 40 insertions, 0 deletions
| diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 00fd02ec1b65..fdba13137daf 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c | |||
| @@ -166,6 +166,8 @@ enum { | |||
| 166 | #define SYSC_IDLEMODE_SMART 0x2 | 166 | #define SYSC_IDLEMODE_SMART 0x2 | 
| 167 | #define SYSC_CLOCKACTIVITY_FCLK 0x2 | 167 | #define SYSC_CLOCKACTIVITY_FCLK 0x2 | 
| 168 | 168 | ||
| 169 | /* Errata definitions */ | ||
| 170 | #define I2C_OMAP_ERRATA_I207 (1 << 0) | ||
| 169 | 171 | ||
| 170 | struct omap_i2c_dev { | 172 | struct omap_i2c_dev { | 
| 171 | struct device *dev; | 173 | struct device *dev; | 
| @@ -199,6 +201,7 @@ struct omap_i2c_dev { | |||
| 199 | u16 bufstate; | 201 | u16 bufstate; | 
| 200 | u16 syscstate; | 202 | u16 syscstate; | 
| 201 | u16 westate; | 203 | u16 westate; | 
| 204 | u16 errata; | ||
| 202 | }; | 205 | }; | 
| 203 | 206 | ||
| 204 | const static u8 reg_map[] = { | 207 | const static u8 reg_map[] = { | 
| @@ -498,6 +501,11 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) | |||
| 498 | /* Take the I2C module out of reset: */ | 501 | /* Take the I2C module out of reset: */ | 
| 499 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); | 502 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); | 
| 500 | 503 | ||
| 504 | dev->errata = 0; | ||
| 505 | |||
| 506 | if (cpu_is_omap2430() || cpu_is_omap34xx()) | ||
| 507 | dev->errata |= I2C_OMAP_ERRATA_I207; | ||
| 508 | |||
| 501 | /* Enable interrupts */ | 509 | /* Enable interrupts */ | 
| 502 | dev->iestate = (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY | | 510 | dev->iestate = (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY | | 
| 503 | OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK | | 511 | OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK | | 
| @@ -695,6 +703,34 @@ omap_i2c_ack_stat(struct omap_i2c_dev *dev, u16 stat) | |||
| 695 | omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat); | 703 | omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat); | 
| 696 | } | 704 | } | 
| 697 | 705 | ||
| 706 | static inline void i2c_omap_errata_i207(struct omap_i2c_dev *dev, u16 stat) | ||
| 707 | { | ||
| 708 | /* | ||
| 709 | * I2C Errata(Errata Nos. OMAP2: 1.67, OMAP3: 1.8) | ||
| 710 | * Not applicable for OMAP4. | ||
| 711 | * Under certain rare conditions, RDR could be set again | ||
| 712 | * when the bus is busy, then ignore the interrupt and | ||
| 713 | * clear the interrupt. | ||
| 714 | */ | ||
| 715 | if (stat & OMAP_I2C_STAT_RDR) { | ||
| 716 | /* Step 1: If RDR is set, clear it */ | ||
| 717 | omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR); | ||
| 718 | |||
| 719 | /* Step 2: */ | ||
| 720 | if (!(omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG) | ||
| 721 | & OMAP_I2C_STAT_BB)) { | ||
| 722 | |||
| 723 | /* Step 3: */ | ||
| 724 | if (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG) | ||
| 725 | & OMAP_I2C_STAT_RDR) { | ||
| 726 | omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR); | ||
| 727 | dev_dbg(dev->dev, "RDR when bus is busy.\n"); | ||
| 728 | } | ||
| 729 | |||
| 730 | } | ||
| 731 | } | ||
| 732 | } | ||
| 733 | |||
| 698 | /* rev1 devices are apparently only on some 15xx */ | 734 | /* rev1 devices are apparently only on some 15xx */ | 
| 699 | #ifdef CONFIG_ARCH_OMAP15XX | 735 | #ifdef CONFIG_ARCH_OMAP15XX | 
| 700 | 736 | ||
| @@ -834,6 +870,10 @@ complete: | |||
| 834 | } | 870 | } | 
| 835 | if (stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)) { | 871 | if (stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)) { | 
| 836 | u8 num_bytes = 1; | 872 | u8 num_bytes = 1; | 
| 873 | |||
| 874 | if (dev->errata & I2C_OMAP_ERRATA_I207) | ||
| 875 | i2c_omap_errata_i207(dev, stat); | ||
| 876 | |||
| 837 | if (dev->fifo_size) { | 877 | if (dev->fifo_size) { | 
| 838 | if (stat & OMAP_I2C_STAT_RRDY) | 878 | if (stat & OMAP_I2C_STAT_RRDY) | 
| 839 | num_bytes = dev->fifo_size; | 879 | num_bytes = dev->fifo_size; | 
