/* I2C controller revisions present on specific hardware */
 #define OMAP_I2C_REV_ON_2430           0x36
 #define OMAP_I2C_REV_ON_3430           0x3C
+#define OMAP_I2C_REV_ON_4430           0x40
 
 /* timeout waiting for the controller to respond */
 #define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
 
-#define OMAP_I2C_REV_REG               0x00
-#define OMAP_I2C_IE_REG                        0x01
-#define OMAP_I2C_STAT_REG              0x02
-#define OMAP_I2C_IV_REG                        0x03
 /* For OMAP3 I2C_IV has changed to I2C_WE (wakeup enable) */
-#define OMAP_I2C_WE_REG                        0x03
-#define OMAP_I2C_SYSS_REG              0x04
-#define OMAP_I2C_BUF_REG               0x05
-#define OMAP_I2C_CNT_REG               0x06
-#define OMAP_I2C_DATA_REG              0x07
-#define OMAP_I2C_SYSC_REG              0x08
-#define OMAP_I2C_CON_REG               0x09
-#define OMAP_I2C_OA_REG                        0x0a
-#define OMAP_I2C_SA_REG                        0x0b
-#define OMAP_I2C_PSC_REG               0x0c
-#define OMAP_I2C_SCLL_REG              0x0d
-#define OMAP_I2C_SCLH_REG              0x0e
-#define OMAP_I2C_SYSTEST_REG           0x0f
-#define OMAP_I2C_BUFSTAT_REG           0x10
+enum {
+       OMAP_I2C_REV_REG = 0,
+       OMAP_I2C_IE_REG,
+       OMAP_I2C_STAT_REG,
+       OMAP_I2C_IV_REG,
+       OMAP_I2C_WE_REG,
+       OMAP_I2C_SYSS_REG,
+       OMAP_I2C_BUF_REG,
+       OMAP_I2C_CNT_REG,
+       OMAP_I2C_DATA_REG,
+       OMAP_I2C_SYSC_REG,
+       OMAP_I2C_CON_REG,
+       OMAP_I2C_OA_REG,
+       OMAP_I2C_SA_REG,
+       OMAP_I2C_PSC_REG,
+       OMAP_I2C_SCLL_REG,
+       OMAP_I2C_SCLH_REG,
+       OMAP_I2C_SYSTEST_REG,
+       OMAP_I2C_BUFSTAT_REG,
+       OMAP_I2C_REVNB_LO,
+       OMAP_I2C_REVNB_HI,
+       OMAP_I2C_IRQSTATUS_RAW,
+       OMAP_I2C_IRQENABLE_SET,
+       OMAP_I2C_IRQENABLE_CLR,
+};
 
 /* I2C Interrupt Enable Register (OMAP_I2C_IE): */
 #define OMAP_I2C_IE_XDR                (1 << 14)       /* TX Buffer drain int enable */
        u32                     speed;          /* Speed of bus in Khz */
        u16                     cmd_err;
        u8                      *buf;
+       u8                      *regs;
        size_t                  buf_len;
        struct i2c_adapter      adapter;
        u8                      fifo_size;      /* use as flag and value
        u16                     westate;
 };
 
+const static u8 reg_map[] = {
+       [OMAP_I2C_REV_REG] = 0x00,
+       [OMAP_I2C_IE_REG] = 0x01,
+       [OMAP_I2C_STAT_REG] = 0x02,
+       [OMAP_I2C_IV_REG] = 0x03,
+       [OMAP_I2C_WE_REG] = 0x03,
+       [OMAP_I2C_SYSS_REG] = 0x04,
+       [OMAP_I2C_BUF_REG] = 0x05,
+       [OMAP_I2C_CNT_REG] = 0x06,
+       [OMAP_I2C_DATA_REG] = 0x07,
+       [OMAP_I2C_SYSC_REG] = 0x08,
+       [OMAP_I2C_CON_REG] = 0x09,
+       [OMAP_I2C_OA_REG] = 0x0a,
+       [OMAP_I2C_SA_REG] = 0x0b,
+       [OMAP_I2C_PSC_REG] = 0x0c,
+       [OMAP_I2C_SCLL_REG] = 0x0d,
+       [OMAP_I2C_SCLH_REG] = 0x0e,
+       [OMAP_I2C_SYSTEST_REG] = 0x0f,
+       [OMAP_I2C_BUFSTAT_REG] = 0x10,
+};
+
+const static u8 omap4_reg_map[] = {
+       [OMAP_I2C_REV_REG] = 0x04,
+       [OMAP_I2C_IE_REG] = 0x2c,
+       [OMAP_I2C_STAT_REG] = 0x28,
+       [OMAP_I2C_IV_REG] = 0x34,
+       [OMAP_I2C_WE_REG] = 0x34,
+       [OMAP_I2C_SYSS_REG] = 0x90,
+       [OMAP_I2C_BUF_REG] = 0x94,
+       [OMAP_I2C_CNT_REG] = 0x98,
+       [OMAP_I2C_DATA_REG] = 0x9c,
+       [OMAP_I2C_SYSC_REG] = 0x20,
+       [OMAP_I2C_CON_REG] = 0xa4,
+       [OMAP_I2C_OA_REG] = 0xa8,
+       [OMAP_I2C_SA_REG] = 0xac,
+       [OMAP_I2C_PSC_REG] = 0xb0,
+       [OMAP_I2C_SCLL_REG] = 0xb4,
+       [OMAP_I2C_SCLH_REG] = 0xb8,
+       [OMAP_I2C_SYSTEST_REG] = 0xbC,
+       [OMAP_I2C_BUFSTAT_REG] = 0xc0,
+       [OMAP_I2C_REVNB_LO] = 0x00,
+       [OMAP_I2C_REVNB_HI] = 0x04,
+       [OMAP_I2C_IRQSTATUS_RAW] = 0x24,
+       [OMAP_I2C_IRQENABLE_SET] = 0x2c,
+       [OMAP_I2C_IRQENABLE_CLR] = 0x30,
+};
+
 static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev,
                                      int reg, u16 val)
 {
-       __raw_writew(val, i2c_dev->base + (reg << i2c_dev->reg_shift));
+       __raw_writew(val, i2c_dev->base +
+                       (i2c_dev->regs[reg] << i2c_dev->reg_shift));
 }
 
 static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg)
 {
-       return __raw_readw(i2c_dev->base + (reg << i2c_dev->reg_shift));
+       return __raw_readw(i2c_dev->base +
+                               (i2c_dev->regs[reg] << i2c_dev->reg_shift));
 }
 
 static int __init omap_i2c_get_clocks(struct omap_i2c_dev *dev)
        WARN_ON(dev->idle);
 
        dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
-       omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0);
+       if (dev->rev >= OMAP_I2C_REV_ON_4430)
+               omap_i2c_write_reg(dev, OMAP_I2C_IRQENABLE_CLR, 1);
+       else
+               omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0);
+
        if (dev->rev < OMAP_I2C_REV_2) {
                iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */
        } else {
                         * REVISIT: Some wkup sources might not be needed.
                         */
                        dev->westate = OMAP_I2C_WE_ALL;
-                       omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate);
+                       if (dev->rev < OMAP_I2C_REV_ON_4430)
+                               omap_i2c_write_reg(dev, OMAP_I2C_WE_REG,
+                                                               dev->westate);
                }
        }
        omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
                        psc = fclk_rate / 12000000;
        }
 
-       if (cpu_is_omap2430() || cpu_is_omap34xx()) {
+       if (!(cpu_class_is_omap1() || cpu_is_omap2420())) {
 
                /*
                 * HSI2C controller internal clk rate should be 19.2 Mhz for
                                if (dev->buf_len) {
                                        *dev->buf++ = w;
                                        dev->buf_len--;
-                                       /* Data reg from 2430 is 8 bit wide */
-                                       if (!cpu_is_omap2430() &&
-                                                       !cpu_is_omap34xx()) {
+                                       /*
+                                        * Data reg in 2430, omap3 and
+                                        * omap4 is 8 bit wide
+                                        */
+                                       if (cpu_class_is_omap1() ||
+                                                       cpu_is_omap2420()) {
                                                if (dev->buf_len) {
                                                        *dev->buf++ = w >> 8;
                                                        dev->buf_len--;
                                if (dev->buf_len) {
                                        w = *dev->buf++;
                                        dev->buf_len--;
-                                       /* Data reg from  2430 is 8 bit wide */
-                                       if (!cpu_is_omap2430() &&
-                                                       !cpu_is_omap34xx()) {
+                                       /*
+                                        * Data reg in 2430, omap3 and
+                                        * omap4 is 8 bit wide
+                                        */
+                                       if (cpu_class_is_omap1() ||
+                                                       cpu_is_omap2420()) {
                                                if (dev->buf_len) {
                                                        w |= *dev->buf++ << 8;
                                                        dev->buf_len--;
 
        if (cpu_is_omap7xx())
                dev->reg_shift = 1;
+       else if (cpu_is_omap44xx())
+               dev->reg_shift = 0;
        else
                dev->reg_shift = 2;
 
        if ((r = omap_i2c_get_clocks(dev)) != 0)
                goto err_iounmap;
 
+       if (cpu_is_omap44xx())
+               dev->regs = (u8 *) omap4_reg_map;
+       else
+               dev->regs = (u8 *) reg_map;
+
        omap_i2c_unidle(dev);
 
        dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
 
-       if (cpu_is_omap2430() || cpu_is_omap34xx()) {
+       if (!(cpu_class_is_omap1() || cpu_is_omap2420())) {
                u16 s;
 
                /* Set up the fifo size - Get total size */
                 * size. This is to ensure that we can handle the status on int
                 * call back latencies.
                 */
-               dev->fifo_size = (dev->fifo_size / 2);
-               dev->b_hw = 1; /* Enable hardware fixes */
+               if (dev->rev >= OMAP_I2C_REV_ON_4430) {
+                       dev->fifo_size = 0;
+                       dev->b_hw = 0; /* Disable hardware fixes */
+               } else {
+                       dev->fifo_size = (dev->fifo_size / 2);
+                       dev->b_hw = 1; /* Enable hardware fixes */
+               }
        }
 
        /* reset ASAP, clearing any IRQs */